如何在命令行中使用超过两个标志来控制相同的行为?

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

How can I have more than only two command-line flags controlling the same behavior?

问题

在Go语言中,我知道如何使用github.com/pborman/getopt包来执行类似于getopt的命令行解析。

然而,这个包似乎只能支持每个命令行选项的一个字符串版本和一个rune版本。有时候我想要的不仅仅是两种指定选项的方式。例如,对于一个名为prog的假设程序,我希望以下所有方式都执行完全相同的功能:

prog -r [其他参数]
prog -R [其他参数]
prog --recurse [其他参数]
prog --recursive [其他参数]

我知道我可以像下面这样做,只需测试每个变量optRecurseoptRecursive的值...

optRecurse   := getopt.BoolLong("recurse",   'r', "run recursively")
optRecursive := getopt.BoolLong("recursive", 'R', "run recursively")

然而,理想情况下,我希望能够通过一次调用来获得这四种可能性中的一个值。

我希望有一种类似于Ruby的OptionParser包的方式,可以处理任何给定命令行选项的两种以上可能性。下面是一个Ruby的例子...

$isRecursive = false
parser = OptionParser.new {
  |opts|
  opts.on('-r', '-R', '--recurse', '--recursive') {
    |arg|
    # 所有四种可能性都在一个单独的"opts.on"块中处理。
    $isRecursive = true
  }
  # ... 其他代码 ...
}

我对Go语言相对较新,我可能在寻找答案时忽略了一些东西。

英文:

In Go, I know how to use the github.com/pborman/getopt package to perform getopt-like command-line parsing.

However, this package only seems to be able to support one string version and one rune version of each command-line option. Sometimes I want more than simply two ways to specify an option. For example, for a hypothetical program called prog, I'd like the following to all perform the exact, same function:

prog -r [other args]
prog -R [other args]
prog --recurse [other args]
prog --recursive [other args]

I know that I can do something like the following and just test for the value of each of the variables optRecurse and optRecursive ...

optRecurse   := getopt.BoolLong("recurse",   'r', "run recursively")
optRecursive := getopt.BoolLong("recursive", 'R', "run recursively")

However, ideally, I'd like to make one, single call that will give me one value for any of these four possibilities.

I want something that works similarly to Ruby's OptionParser package with regard to more than two possibilities for any given command-line option. Here's a Ruby example ...

$isRecursive = false
parser = OptionParser.new {
  |opts|
  opts.on('-r', '-R', '--recurse', '--recursive') {
    |arg|
    # All four possibilities are handled with one, single "opts.on" block.
    $isRecursive = true
  }
  # ... etc. ...
}

I'm relatively new to Go, and I may very well have overlooked something in my searches for an answer to this question.

答案1

得分: 1

在我看来,提供超过两种方式来指定任何给定的命令行选项并不“奇怪”。

我最初在这个“回答”中提到的github.com/clagraff/argparse包已经不再受支持。然而,我找到了一个更现代且仍受支持的包,可以使用它以类似于其他语言(如Ruby和Python)的参数解析包所提供的方式来实现这种功能:github.com/tcler/cmdline-go/cmdline

以下是一个示例程序,演示了如何在Go中实现这一点...

package main                  

import (
	"fmt";
	"os";
	"github.com/tcler/cmdline-go/cmdline";
)

func main() {
	var nargv []string = os.Args[1:]
	var cli cmdline.Cmdline

	var options = []cmdline.Option {
		{Help: "Options:"},
		{Names: "r R recurse recursive", Argtype: cmdline.N, Help: "Run recursively"},
	}

	cli = cmdline.Parse(options, nargv)

	has_invalid := false
	for _, v := range cli.InvalidOptions {
		if !has_invalid {
			fmt.Println()
		}
		fmt.Println(v)
		has_invalid = true
	}
	if has_invalid {
		fmt.Println()
		cmdline.GetUsage(options)
		os.Exit(1)
	}

	recursivemode := cli.GetOptionArgString("r")
	fmt.Printf("recursive mode: \"%s\"\n", recursivemode)
}

我可以以以下四种方式运行该程序,它在每种情况下的行为都相同...

% go run prog.go -r
% go run prog.go -R
% go run prog.go --recurse
% go run prog.go --recursive

在这四种情况下,它总是输出以下内容:

recursive mode: "set"

如果我不带任何选项运行(即仅运行go run prog.go),它会输出:

recursive mode: ""

如果我带有任何其他命令行参数运行,例如-x,它会失败并显示以下内容:

% go run prog.go -x

option: 'x' undefined

Options:
     -r -R --recurse --recursive
                               Run recursively

[加上一些其他的“帮助”文本]

因此,现在我可以编写允许使用多于两种方式来指定任何命令行选项的Go程序。

<details>
<summary>英文:</summary>

In my opinion, there is nothing &quot;odd&quot; about offering more than two ways to specify any given command-line option.

The `github.com/clagraff/argparse` package that I originally mentioned here in this &quot;Answer&quot; is no longer being supported. However, I found a more modern and still supported package that I can use which offers that exact capability in a manner which is similar to what&#39;s offered in argument-parsing packages for other languages such as Ruby and Python: `github.com/tcler/cmdline-go/cmdline`.

Here is a sample program which illustrates how this can work in Go ...

    package main                  
    
    import (
    	&quot;fmt&quot;;
    	&quot;os&quot;;
    	&quot;github.com/tcler/cmdline-go/cmdline&quot;;
    )
    
    func main() {
    	var nargv []string = os.Args[1:]
    	var cli cmdline.Cmdline
    
    	var options = []cmdline.Option {
    		{Help: &quot;Options:&quot;},
    		{Names: &quot;r R recurse recursive&quot;, Argtype: cmdline.N, Help: &quot;Run recursively&quot;},
    	}
    
    	cli = cmdline.Parse(options, nargv)
    
    	has_invalid := false
    	for _, v := range cli.InvalidOptions {
    		if !has_invalid {
    			fmt.Println()
    		}
    		fmt.Println(v)
    		has_invalid = true
    	}
    	if has_invalid {
    		fmt.Println()
    		cmdline.GetUsage(options)
            os.Exit(1)
    	}

        recursivemode := cli.GetOptionArgString(&quot;r&quot;)
        fmt.Printf(&quot;recursive mode: \&quot;%s\&quot;\n&quot;, recursivemode)
    }

I can run the program in all four of the following ways, and it behaves the same in each case ...

    % go run prog.go -r
    % go run prog.go -R
    % go run prog.go --recurse
    % go run prog.go --recursive

In all four of these these cases, it always outputs the following:

    recursive mode: &quot;set&quot;

If I run without any option (*i.e.*, simply `go run prog.go`), it outputs this:

    recursive mode: &quot;&quot;

And if I run with any other command-line argument, such as `-x` for example, it fails as follows:

    % go run prog.go -x

    option: &#39;x&#39; undefined
    
    Options:
         -r -R --recurse --recursive
                                   Run recursively
    
    [ plus some other &quot;help&quot; text ]

So, now I can write Go programs which allow more than two ways to specify any command-line option.


</details>



huangapple
  • 本文由 发表于 2023年3月2日 07:15:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75609941.html
匿名

发表评论

匿名网友

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

确定