命令行界面实现的建议

37

我正在重新设计一个命令行应用程序,希望找到一种使其使用更加直观的方法。有没有关于命令行应用程序参数格式的惯例?或者其他人发现有用的任何方法?


5
了解您的目标环境可能会有所帮助。 - dmckee --- ex-moderator kitten
17个回答

29

我看到很多与Windows命令行有关的内容,但是如果你的程序面向Linux,我认为GNU命令行标准最直观。基本上,它使用双破折号表示命令的长格式(例如--help),使用单破折号表示其简写版本(例如-h)。您还可以将短版一起“堆叠”(例如tar -zxvf 文件名),并随心所欲地混合使用长和短版本。

GNU网站还列出了标准选项名称

getopt库极大地简化了解析这些命令的过程。如果C不是您的菜,Python有一个类似的库,Perl也有它的库


4
在Windows中,无参开关的事实标准是使用“/foo”(但也支持“-foo”,类似于BSD风格),而带参数的开关则是使用“/foo:value”(同样支持“-foo:value”)。换句话说,这是所有Microsoft命令行工具(Win32开箱即用、开发工具等)所使用的语法。 - Pavel Minaev
在Python中,使用optparse - http://docs.python.org/library/optparse.html - 它比getopt好用多了。 - dbr
1
@dbr,optparse现在已经被弃用了,推荐使用http://docs.python.org/library/argparse.html。 - Teo Klestrup Röijezon
“Bundling”这个术语可能比“stacking”更常用,用于描述将短选项组合在一起的做法。 - Todd Freed

14
如果您正在使用C#,可以尝试使用Mono.GetOptions,它是一个非常强大且易于使用的命令行参数解析器。 它在Mono环境和Microsoft .NET Framework中都能工作。
编辑:以下是一些功能:
  • 每个参数都有两个CLI表示(1个字符和字符串,例如-a或--add)
  • 默认值
  • 强类型
  • 自动创建带有说明的帮助屏幕
  • 自动生成版本和版权屏幕

4
看起来Mono正在废弃它们自己的选项解析库并转而使用NDesk.Options: http://ndesk.org/Options - quip

4
今日免费次数已满, 请开通会员/明日再来
myCli.exe describe someThing
myCli.exe descr someThing
myCli.exe desc someThing

那样,用户就不必每次都输入完整命令。

这种方法在像Darcs、Git和Subversion这样的工具中特别有用,因为它们本质上是一组相关但不同的命令。 - Josh Lee
没错!除了我使用那个功能来操作另一个版本控制命令行界面:ClearCase的cleartool(ct);)。由于我还管理Subversion存储库,因此我也会使用svn和svnadmin命令... - VonC

4

一个好的和有帮助的参考资料:

https://commandline.codeplex.com/

通过NuGet可用的库:

  1. 最新稳定版:Install-Package CommandLineParser
  2. 最新发布版:Install-Package CommandLineParser -pre

使用默认单例进行一行解析:CommandLine.Parser.Default.ParseArguments(...)
一行帮助屏幕生成器:HelpText.AutoBuild(...)
将命令行参数映射到IList<string>、数组、枚举或标准标量类型。
插件友好的体系结构,如此处所述。
定义动词命令:git commit -a
使用Lambda表达式创建解析器实例。

快速入门:https://commandline.codeplex.com/wikipage?title=Quickstart&referringTitle=Documentation

// Define a class to receive parsed values
class Options {
  [Option('r', "read", Required = true,
    HelpText = "Input file to be processed.")]
  public string InputFile { get; set; }

  [Option('v', "verbose", DefaultValue = true,
    HelpText = "Prints all messages to standard output.")]
  public bool Verbose { get; set; }

  [ParserState]
  public IParserState LastParserState { get; set; }

  [HelpOption]
  public string GetUsage() {
    return HelpText.AutoBuild(this,
      (HelpText current) => HelpText.DefaultParsingErrorsHandler(this, current));
  }
}

// Consume them
static void Main(string[] args) {
  var options = new Options();
  if (CommandLine.Parser.Default.ParseArguments(args, options)) {
    // Values are available here
    if (options.Verbose) Console.WriteLine("Filename: {0}", options.InputFile);
  }
}

这个命令行解析器已经有了一个新家 - AlexMelw

3

最好的做法是,如果可以的话,不要假定任何东西。当操作员键入您的应用程序名称以进行执行并且没有任何参数时,请向他们显示使用说明块或者在另一种情况下打开一个Windows窗体并允许他们输入您所需的所有内容。

c:\>FOO

FOO

USAGE FOO -{Option}{Value}

-A Do A stuff
-B Do B stuff

c:\>

我将把参数分隔放在宗教话题的标题下:连字符(破折号),双破折号,斜杠,空白,位置等。

您没有说明您的平台,但是对于下一个评论,我将假设Windows和.net

您可以在.net中创建基于控制台的应用程序,并通过选择控制台项目然后添加Windows.Forms、System.Drawing等DLL来允许其与桌面交互。

我们经常这样做。这确保了没有人走进黑暗的小巷。


3

我已经看过了。它似乎太简单了。 - Gqqnbig

3
命令行约定因操作系统而异,但可能得到最多使用和最多公众关注的是由GNU getopt软件包支持的约定。有关更多信息,请参见http://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html
它允许您混合单字母命令(例如-nr)与更长的自我说明选项(例如--numeric --reverse)。友好一些,实现--help(-?)选项,然后您的用户将能够找到他们所需的所有信息。

3

补充 @vonc 的回答,不要接受含糊不清的缩写。例如:

  myCli.exe describe someThing
  myCli.exe destroy someThing
  myCli.exe des someThing ???

事实上,在那种情况下,我可能不会接受“destroy”的缩写...


2
好观点,消除歧义是另一个需要考虑的标准... 您做得很好,先生。 - VonC

2
我总是添加一个 /? 参数来获取帮助,并尝试使用默认的实现(即最常见的场景)。
否则,我倾向于使用 "/x" 作为开关,使用 "/x:value" 作为需要传递值的开关。这样可以很容易地使用正则表达式解析参数。

1

我开发了这个框架,也许可以帮到你:

SysCommand是一个强大的跨平台框架,用于在.NET中开发控制台应用程序。它很简单,类型安全,并且受MVC模式的很大影响。

https://github.com/juniorgasparotto/SysCommand

namespace Example.Initialization.Simple
{
    using SysCommand.ConsoleApp;

    public class Program
    {
        public static int Main(string[] args)
        {
            return App.RunApplication();
        }
    }

    // Classes inheriting from `Command` will be automatically found by the system
    // and its public properties and methods will be available for use.
    public class MyCommand : Command
    {
        public void Main(string arg1, int? arg2 = null)
        {
            if (arg1 != null)
                this.App.Console.Write(string.Format("Main arg1='{0}'", arg1));
            if (arg2 != null)
                this.App.Console.Write(string.Format("Main arg2='{0}'", arg2));
        }

        public void MyAction(bool a)
        {
            this.App.Console.Write(string.Format("MyAction a='{0}'", a));
        }
    }
}

测试:
// auto-generate help
$ my-app.exe help

// method "Main" typed
$ my-app.exe --arg1 value --arg2 1000

// or without "--arg2"
$ my-app.exe --arg1 value

// actions support
$ my-app.exe my-action -a

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接