在Go中实现类似于getopt的行为

huangapple go评论127阅读模式
英文:

getopt-like behavior in Go

问题

如何优雅地解析程序参数列表并自动处理“--help”和/或“--version”(例如“program [-d value] [--abc] [FILE1]”)在Go中?

英文:

How do I nicely parse a list of program parameters and automate handling "--help" and/or "--version" (such as "program [-d value] [--abc] [FILE1]") in Go?

答案1

得分: 25

Google已经创建了一个getopt包(import "github.com/pborman/getopt"),它提供了更标准的命令行解析方式(与'flag'包相比)。

package main

import (
	"fmt"
	"os"
	"github.com/pborman/getopt"
)

func main() {
	optName := getopt.StringLong("name", 'n', "", "Your name")
	optHelp := getopt.BoolLong("help", 0, "Help")
	getopt.Parse()

	if *optHelp {
		getopt.Usage()
		os.Exit(0)
	}

	fmt.Println("Hello " + *optName + "!")
}

 

$ ./hello --help
Usage: hello [--help] [-n value] [parameters ...]
     --help        帮助
 -n, --name=value  你的名字

$ ./hello --name Bob
Hello Bob!
英文:

Google has created a getopt package (import "github.com/pborman/getopt") which provides the more standard command line parsing (vs the 'flag' package).

package main

import (
	"fmt"
	"os"
	"github.com/pborman/getopt"
)

func main() {
	optName := getopt.StringLong("name", 'n', "", "Your name")
	optHelp := getopt.BoolLong("help", 0, "Help")
	getopt.Parse()

	if *optHelp {
		getopt.Usage()
		os.Exit(0)
	}

	fmt.Println("Hello " + *optName + "!")
}

 

$ ./hello --help
Usage: hello [--help] [-n value] [parameters ...]
     --help        Help
 -n, --name=value  Your name

$ ./hello --name Bob
Hello Bob!

答案2

得分: 15

使用'flag'包:http://golang.org/pkg/flag/。但是它不支持双破折号参数。目前还没有完全模仿GNU getopt行为的东西。

英文:

Use the 'flag' package: http://golang.org/pkg/flag/. It doesn't do double-dash arguments, however. There isn't anything that exactly mimics GNU getopt behaviour (yet.)

答案3

得分: 11

从“命令行UI”部分开始,您有几个能够解析getopt-long参数的库。

我尝试了Go1.0.2版本:

示例:

package main

import (
	"fmt"
	goopt "github.com/droundy/goopt"
)

func main() {
	fmt.Println("flag")
	goopt.NoArg([]string{"--abc"}, "abc参数,无值", noabc)

	goopt.Description = func() string {
		return "使用goopt标志库的示例程序。"
	}
	goopt.Version = "1.0"
	goopt.Summary = "goopt演示程序"
	goopt.Parse(nil)
}

func noabc() error {
	fmt.Println("您应该有一个--abc参数")
	return nil
}

goopt提供的其他默认参数:

 --help               显示生成的帮助消息(调用Help())
 --create-manpage     显示由goopt库生成的man页(使用Author、Suite等)
 --list-options       列出所有已知标志
英文:

From the section "Command Line UI", you have several libraries able to parse getopt-long parameters.

I tried, with a Go1.0.2:

Example:

package main

import (
	"fmt"
	goopt "github.com/droundy/goopt"
)

func main() {
	fmt.Println("flag")
	goopt.NoArg([]string{"--abc"}, "abc param, no value", noabc)

	goopt.Description = func() string {
		return "Example program for using the goopt flag library."
	}
	goopt.Version = "1.0"
	goopt.Summary = "goopt demonstration program"
	goopt.Parse(nil)
}

func noabc() error {
	fmt.Println("You should have an --abc parameter")
	return nil
}

Other default parameters provided with goopt:

 --help               Display the generated help message (calls Help())
 --create-manpage     Display a manpage generated by the goopt library (uses Author, Suite, etc)
 --list-options       List all known flags

答案4

得分: 7

go-flags非常完整,采用BSD许可证,并且有一个清晰的示例

var opts struct {
      DSomething string `short:"d" description:"无论这是什么" required:"true"`
      ABC bool `long:"abc" description:"某事"`
}

fileArgs, err := flags.Parse(&opts)

if err != nil {
    os.Exit(1)
}
英文:

go-flags is very complete, BSD licensed, and has a clear example.

var opts struct {
      DSomething string `short:"d" description:"Whatever this is" required:"true"`
      ABC bool `long:"abc" description:"Something"`
}

fileArgs, err := flags.Parse(&opts)

if err != nil {
    os.Exit(1)
}

答案5

得分: 5

我为你做了以下翻译:

package main

import (
    "fmt";
    "os"
)

func main() {
    for i, arg := range os.Args {
        if arg == "-help" {
            fmt.Printf("我需要有人\n")
        } else if arg == "-version" {
            fmt.Printf("版本零\n")
        } else {
            fmt.Printf("参数 %d: %s\n", i, os.Args[i])
        }
    }
}

参见 https://play.golang.org/p/XtNXG-DhLI

测试:

$ ./8.out -help -version monkey business
我需要有人
版本零
参数 3: monkey
参数 4: business
英文:

I made it just for you:

package main

import (
  "fmt";
  "os"
)

func main() {
  for i, arg := range os.Args {
    if arg == "-help" {
      fmt.Printf ("I need somebody\n")
    }else if arg == "-version" {
      fmt.Printf ("Version Zero\n")
    } else {
      fmt.Printf("arg %d: %s\n", i, os.Args[i])
    }
  }
}

see also https://play.golang.org/p/XtNXG-DhLI

Test:
<pre>
$ ./8.out -help -version monkey business
I need somebody
Version Zero
arg 3: monkey
arg 4: business
</pre>

答案6

得分: 5

另一个选择是Kingpin,它提供了对现代命令行解析库的所有标准功能的支持。它支持多种格式的--help,子命令,要求,类型,默认值等等。它仍在开发中。这里的其他建议似乎已经有一段时间没有更新了。

package main

import (
  "os"
  "strings"
  "gopkg.in/alecthomas/kingpin.v2"
)

var (
  app      = kingpin.New("chat", "一个命令行聊天应用程序。")
  debug    = app.Flag("debug", "启用调试模式。").Bool()
  serverIP = app.Flag("server", "服务器地址。").Default("127.0.0.1").IP()

  register     = app.Command("register", "注册一个新用户。")
  registerNick = register.Arg("nick", "用户的昵称。").Required().String()
  registerName = register.Arg("name", "用户的姓名。").Required().String()

  post        = app.Command("post", "向频道发布消息。")
  postImage   = post.Flag("image", "要发布的图片。").File()
  postChannel = post.Arg("channel", "要发布到的频道。").Required().String()
  postText    = post.Arg("text", "要发布的文本。").Strings()
)

func main() {
  switch kingpin.MustParse(app.Parse(os.Args[1:])) {
  // 注册用户
  case register.FullCommand():
    println(*registerNick)

  // 发布消息
  case post.FullCommand():
    if *postImage != nil {
    }
    text := strings.Join(*postText, " ")
    println("发布:", text)
  }
}

--help 输出如下:

$ chat --help
用法:chat [<flags>] <command> [<flags>] [<args> ...]

一个命令行聊天应用程序。

标志:
  --help              显示帮助。
  --debug             启用调试模式。
  --server=127.0.0.1  服务器地址。

命令:
  help [<command>]
    显示命令的帮助信息。

  register <nick> <name>
    注册一个新用户。

  post [<flags>] <channel> [<text>]
    向频道发布消息。
英文:

Another option is Kingping which provides support for all the standard goodies you have come to expect from a modern command line parsing library. It has --help in multiple formats, sub-commands, requirements, types, defaults, etc. It's also still under development. It seems like the other suggestions here haven't been updated in a while.

package main

import (
  &quot;os&quot;
  &quot;strings&quot;
  &quot;gopkg.in/alecthomas/kingpin.v2&quot;
)

var (
  app      = kingpin.New(&quot;chat&quot;, &quot;A command-line chat application.&quot;)
  debug    = app.Flag(&quot;debug&quot;, &quot;Enable debug mode.&quot;).Bool()
  serverIP = app.Flag(&quot;server&quot;, &quot;Server address.&quot;).Default(&quot;127.0.0.1&quot;).IP()

  register     = app.Command(&quot;register&quot;, &quot;Register a new user.&quot;)
  registerNick = register.Arg(&quot;nick&quot;, &quot;Nickname for user.&quot;).Required().String()
  registerName = register.Arg(&quot;name&quot;, &quot;Name of user.&quot;).Required().String()

  post        = app.Command(&quot;post&quot;, &quot;Post a message to a channel.&quot;)
  postImage   = post.Flag(&quot;image&quot;, &quot;Image to post.&quot;).File()
  postChannel = post.Arg(&quot;channel&quot;, &quot;Channel to post to.&quot;).Required().String()
  postText    = post.Arg(&quot;text&quot;, &quot;Text to post.&quot;).Strings()
)

func main() {
  switch kingpin.MustParse(app.Parse(os.Args[1:])) {
  // Register user
  case register.FullCommand():
    println(*registerNick)

  // Post message
  case post.FullCommand():
    if *postImage != nil {
    }
    text := strings.Join(*postText, &quot; &quot;)
    println(&quot;Post:&quot;, text)
  }
}

And the --help output:

$ chat --help
usage: chat [&lt;flags&gt;] &lt;command&gt; [&lt;flags&gt;] [&lt;args&gt; ...]

A command-line chat application.

Flags:
  --help              Show help.
  --debug             Enable debug mode.
  --server=127.0.0.1  Server address.

Commands:
  help [&lt;command&gt;]
    Show help for a command.

  register &lt;nick&gt; &lt;name&gt;
    Register a new user.

  post [&lt;flags&gt;] &lt;channel&gt; [&lt;text&gt;]
    Post a message to a channel.

答案7

得分: 3

我认为你想要的是docopt。我只是会引用我之前发布的一个答案来提供详细信息。

英文:

I think what you want is docopt. I'll just refer you to an earlier answer I posted for the details.

答案8

得分: 2

作为一个简单的库,自2017年8月以来,你有github.com/rsc/getopt

> 要使用,请像使用flag包一样定义标志。然后通过调用getopt.Alias来引入任何别名:

getopt.Alias("v", "verbose")

> 或者调用getopt.Aliases来定义别名列表:

getopt.Aliases(
    "v", "verbose",
    "x", "xylophone",
)

并且:

> 一般来说,对于新程序,更倾向于使用Go标志解析,因为它对于调用标志所使用的破折号数量不那么严格(你可以写-verbose--verbose,程序不会在意)。
>
> 这个包的用途是在需要使用完全符合**getopt(3)**语法的情况下使用,比如在使用Go重写已经使用getopt(3)的现有工具时。

英文:

As a simple library, you have since August 2017 github.com/rsc/getopt

> To use, define flags as usual with package flag. Then introduce any aliases by calling getopt.Alias:

getopt.Alias(&quot;v&quot;, &quot;verbose&quot;)

> Or call getopt.Aliases to define a list of aliases:

getopt.Aliases(
    &quot;v&quot;, &quot;verbose&quot;,
    &quot;x&quot;, &quot;xylophone&quot;,
)

And:

> In general Go flag parsing is preferred for new programs, because it is not as pedantic about the number of dashes used to invoke a flag (you can write -verbose or --verbose, and the program does not care).
>
> This package is meant to be used in situations where, for legacy reasons, it is important to use exactly getopt(3) syntax, such as when rewriting in Go an existing tool that already uses getopt(3).

答案9

得分: 0

可以简单地使用Golang自带的库"flag"来实现。它有很多代码可以用来创建GoLang中的CLI应用程序。例如:

srcDir := flag.String("srcDir", "", "输入csv文件的源目录。")

上述flag库的String方法将从命令提示符中期望一个参数。

请访问https://golang.org/pkg/flag/了解更多信息。

愉快学习...

英文:

One can simply use Golang own library "flag".

It has pretty much code to create CLI like application in GoLang. for Example :

srcDir := flag.String(&quot;srcDir&quot;, &quot;&quot;, &quot;Source directory of the input csv file.&quot;)

The above String method of flag library will expect one argument from command prompt.

Go to https://golang.org/pkg/flag/ for more reading.

Happy Learning...

huangapple
  • 本文由 发表于 2009年11月11日 18:07:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/1714236.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定