23

Go 文档(http://golang.org/pkg/flag/)说:

FlagSet 类型允许定义独立的标志集,例如在命令行界面中实现子命令。

我需要这个功能,但我不知道如何说服标志 pkg 这样做。当我定义两个 FlagSet 时,如果命令行具有用于第二个的标志,则解析其中一个会给我错误和警告。例子:

f1 := flag.NewFlagSet("f1", flag.ContinueOnError)
apply := f1.Bool("apply", false, "")
silent := f1.Bool("silent", false, "")
if err := f1.Parse(os.Args[1:]); err == nil {
    fmt.Println(*apply, *silent)
}
f2 := flag.NewFlagSet("f2", flag.ContinueOnError)
reset := f2.Bool("reset", false, "")
if err := f2.Parse(os.Args[1:]); err == nil {
    fmt.Println(*reset)
}

cmd -apply如果我尝试执行OR ,我会收到各种警告cmd -reset。我想将这些 FlagSet 分开,因为我只想-silent-apply.

我错过了什么?

4

3 回答 3

47

你的意思是先区分子命令,然后Parse在右边调用FlagSet

f1 := flag.NewFlagSet("f1", flag.ContinueOnError)
silent := f1.Bool("silent", false, "")
f2 := flag.NewFlagSet("f2", flag.ContinueOnError)
loud := f2.Bool("loud", false, "")

switch os.Args[1] {
  case "apply":
    if err := f1.Parse(os.Args[2:]); err == nil {
      fmt.Println("apply", *silent)
    }
  case "reset":
    if err := f2.Parse(os.Args[2:]); err == nil {
      fmt.Println("reset", *loud)
    }
}

http://play.golang.org/p/eaEEx_EReX

于 2014-07-01T12:15:10.923 回答
0

事实证明,可以在捕获第一组未识别的标志的同时使用一组标志,并丢弃标志包在遇到无法识别的选项时准备发出的错误消息。

这是一种方法。

    // Start of gentle flag processing.

    // Use the flag package to process the flags we have defined, but collect the arguments that we
    // haven't defined into the passon list. Discard the flag package errors while it finds
    // arguments it doesn't handle.
    flag.CommandLine.Init(os.Args[0], flag.ContinueOnError)
    flag.CommandLine.SetOutput(ioutil.Discard)

    passon := []string{}
    next := os.Args[1:]            // Where to have Parse start

    for len(next) > 0 {
        if next[0] == "--" {
            passon = append(passon, next...) // include the "--" for the next pass, it's what "go test" does. Not everyone will want this/need this.
            break
        }
        err := flag.CommandLine.Parse(next)
        if err == nil {
            passon = append(passon, flag.Args()...)
            break
        }
        if strings.HasPrefix(err.Error(), "flag provided but not defined: ") {
            passon = append(passon, next[0])
            next = next[1:]
            continue
        }
        w := os.Stderr
        fmt.Fprintf(w, "%s\n", err)
        flag.CommandLine.SetOutput(w)
        flag.Usage()
        os.Exit(1)
    }
    // End of gentle flag processing.
于 2022-03-05T22:47:16.587 回答
-1

只需更改这些代码

if err := f2.Parse(os.Args[1:]); err == nil {
    fmt.Println(*reset)
}

f2.Parse(os.Args[1:])
fmt.Println(*reset)

但警告只是留在控制台上。如果你想删除它,修改 /usr/local/go/src/flag/flag.go 并重新编译 golang .. 或复制 flag 包。

  →_→ 怀疑的眼神~~

于 2018-05-29T09:07:43.513 回答