62

GO学习笔记 - 命令行解析

 4 years ago
source link: https://www.tuicool.com/articles/nEfeiuY
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
YF73euJ.png!web

image

本文主题:基于os.Args与flag实现Golang命令行解析。

小慢哥的原创文章,欢迎转载

目录

▪ 一. os.Args

▪ 二. flag

▪ 三. 结合os.Args与flag实现子命令

▪ 附. 参考文档

一. os.Args

os.Args用于获取通过命令行传入的参数

os.Args[0] :程序执行路径

os.Args[1] :第1个参数

os.Args[2] :第2个参数

len(os.Args) :参数数量

示例如下

package main

import (
    "fmt"
    "os"
)

func main() {
    fmt.Println("Program:", os.Args[0])
    for i, v := range os.Args[1:] {
        fmt.Printf("Arg[%d]: %v\n", i, v)
    }
}

测试效果

# 编译执行
go build arg.go
./arg foo "hello world" bar

# 输出
Program: ./arg
Arg[0]: foo
Arg[1]: hello world
Arg[2]: bar

二. flag

golang内置的flag模块可以实现命令行flag解析。

什么是flag,举例说明(加粗部分就是flag):

▷ wc -l

▷ ./configure --prefix=/usr/local/nginx

示例如下(摘取自gobyexample)

package main

import (
    "flag"
    "fmt"
)

func main() {
    // flag.String返回的是指针
    // word表示参数名,foo表示默认值,a string表示参数释义(在-h或解析异常时候会看到)
    // flag.Int、flag.Bool与flag.String同理,不再赘述
    wordPtr := flag.String("word", "foo", "a string")
    numbPtr := flag.Int("numb", 42, "an int")
    boolPtr := flag.Bool("fork", false, "a bool")

    // flag.StringVar返回的是非指针
    var svar string
    flag.StringVar(&svar, "svar", "bar", "a string var")

    // 进行flag解析
    flag.Parse()

    fmt.Println("word:", *wordPtr)
    fmt.Println("numb:", *numbPtr)
    fmt.Println("fork:", *boolPtr)
    fmt.Println("svar:", svar)
    fmt.Println("tail:", flag.Args())
}

测试效果

# 编译
go build flag.go

./flag -word=opt -numb=7 -fork -svar=flag
# 输出
word: opt
numb: 7
fork: true
svar: flag
tail: []

./flag -word=opt
# 输出
word: opt
numb: 42
fork: false
svar: bar
tail: []

./flag -word=opt a1 a2 a3
# 输出
word: opt
numb: 42
fork: false
svar: bar
tail: [a1 a2 a3]

./flag -word=opt a1 a2 a3 -numb=7
# 输出
word: opt
numb: 42
fork: false
svar: bar
tail: [a1 a2 a3 -numb=7]

./flag -h
# 输出
Usage of ./flag:
  -fork
        a bool
  -numb int
        an int (default 42)
  -svar string
        a string var (default "bar")
  -word string
        a string (default "foo")

./flag -wat
# 输出
flag provided but not defined: -wat
Usage of ./flag:
...

该例子,在测试时候只使用了“单横线+参数名”,实际有4种方式,效果是相同的

-word opt
-word=opt
--word opt
--word=opt

三. 结合os.Args与flag实现子命令

如果想实现子命令效果,例如:

▷ docker ps --last 10

▷ docker images --help

这需要将os.Args和flag结合使用。基本原理:创建多个flag集合(即*flag.FlagSet),每个flag集合对应不同的os.Args

示例如下(摘取自gobyexample)

package main

import (
    "flag"
    "fmt"
    "os"
)

func main() {
    fooCmd := flag.NewFlagSet("foo", flag.ExitOnError)
    fooEnable := fooCmd.Bool("enable", false, "enable")
    fooName := fooCmd.String("name", "", "name")

    barCmd := flag.NewFlagSet("bar", flag.ExitOnError)
    barLevel := barCmd.Int("level", 0, "level")

    if len(os.Args) < 2 {
        fmt.Println("expected 'foo' or 'bar' subcommands")
        os.Exit(1)
    }

    switch os.Args[1] {
    case "foo":
        fooCmd.Parse(os.Args[2:])
        fmt.Println("subcommand 'foo'")
        fmt.Println(" enable:", *fooEnable)
        fmt.Println(" name:", *fooName)
        fmt.Println(" tail:", fooCmd.Args())
    case "bar":
        barCmd.Parse(os.Args[2:])
        fmt.Println("subcommand 'bar'")
        fmt.Println(" level:", *barLevel)
        fmt.Println(" tail:", barCmd.Args())
    default:
        fmt.Println("expected 'foo' or 'bar' subcommands")
        os.Exit(1)
    }
}

测试效果

# 编译
go build subflag.go

./subflag foo -enable -name=joe a1 a2
# 输出
subcommand 'foo'
  enable: true
  name: joe
  tail: [a1 a2]

./subflag bar -level 8 a1
# 输出
subcommand 'bar'
  level: 8
  tail: [a1]

./subflag bar -enable a1
# 输出
flag provided but not defined: -enable
Usage of bar:
  -level int
        level

附. 参考文档

# os.Args
https://gobyexample.com/command-line-arguments

# flag
https://gobyexample.com/command-line-flags

# 子命令
https://gobyexample.com/command-line-subcommands

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK