重要
System.CommandLine
目前为预览版,本文档适用于版本 2.0 beta 5。
某些信息与预发布产品有关,该产品在发布前可能会进行大幅修改。 Microsoft对此处提供的信息不作任何明示或暗示的保证。
本文介绍可识别的 System.CommandLine
命令行语法。 此信息对 .NET 命令行应用(包括 .NET CLI)的用户和开发人员都很有用。
令牌
System.CommandLine
将命令行输入分析为标记,这些 标记是用空格分隔的字符串。 例如,请考虑以下命令行:
dotnet tool install dotnet-suggest --global --verbosity quiet
此输入由dotnet
应用程序分析为标记tool
、install
、dotnet-suggest
、--global
和--verbosity
quiet
。
令牌解释为命令、选项或参数。 当前调用的命令行应用会确定如何解释第一个令牌之后的令牌。 下表显示了如何 System.CommandLine
解释前面的示例:
令牌 | 分析为 |
---|---|
tool |
子命令 |
install |
子命令 |
dotnet-suggest |
安装命令的参数 |
--global |
安装命令的选项 |
--verbosity |
安装命令的选项 |
quiet |
--verbosity 选项的自变量 |
如果令牌括在引号 ("
) 中,则可以包含空格。 下面是一个示例:
dotnet tool search "ef migrations add"
指令
命令行输入中的 命令 是指定作或定义一组相关作的标记。 例如:
- 在
dotnet run
中,run
是一个指定动作的命令。 -
dotnet tool install
中,install
是一个指定动作的命令,而tool
是一个指定一组相关命令的命令。 还有其他与工具相关的命令,例如tool uninstall
,tool list
和tool update
。
Root 命令
根命令是指定应用可执行文件的名称的命令。 例如, dotnet
该命令指定 dotnet.exe 可执行文件。
System.CommandLine.Command
是任何命令或子命令的常规用途类,是 System.CommandLine.RootCommand
专用版本,适用于应用程序的根入口点,继承但添加特定于根的行为和默认值的所有功能 System.CommandLine.Command
,例如 帮助选项、 版本选项 和 Suggest 指令。
子命令
大多数命令行应用都支持 子命令,也称为 谓词。 例如,dotnet
命令具有通过输入 run
进行调用的 dotnet run
子命令。
子命令可以有自己的子命令。 在dotnet tool install
中,install
是tool
的一个子命令。
可以添加子命令,如以下示例所示:
RootCommand rootCommand = new();
Command sub1Command = new("sub1", "First-level subcommand");
rootCommand.Subcommands.Add(sub1Command);
Command sub1aCommand = new("sub1a", "Second level subcommand");
sub1Command.Subcommands.Add(sub1aCommand);
此示例中最内部的子命令可以调用如下:
myapp sub1 sub1a
选项
选项是可传递给命令的命名参数。
POSIX CLIs 通常为选项名称加上两个连字符(--
)。 以下示例显示了两个选项:
dotnet tool update dotnet-suggest --verbosity quiet --global
^---------^ ^------^
如本示例所示,选项的值可以是显式(quiet
对于 --verbosity
)或隐式(没有内容跟随 --global
)。 没有指定值的选项通常是在命令行上指定选项时默认 true
的布尔参数。
对于某些 Windows 命令行应用,可以使用带选项名称的前导斜杠(/
)来标识选项。 例如:
msbuild /version
^------^
System.CommandLine
支持 POSIX 和 Windows 前缀约定。
配置选项时,请指定选项名称,包括前缀:
Option<int> delayOption = new("--delay", "-d")
{
Description = "An option whose argument is parsed as an int.",
DefaultValueFactory = parseResult => 42,
};
Option<string> messageOption = new("--message", "-m")
{
Description = "An option whose argument is parsed as a string."
};
RootCommand rootCommand = new();
rootCommand.Options.Add(delayOption);
rootCommand.Options.Add(messageOption);
若要向命令添加一个选项,并递归添加到其所有子命令,请使用该 System.CommandLine.Symbol.Recursive
属性。
必需选项
某些选项具有必需的自变量。 例如,在 .NET CLI 中, --output
需要文件夹名称参数。 如果未提供参数,该命令将失败。 若要使选项是必需的,请将其 System.CommandLine.Symbol.Required
属性设置为 true
,如以下示例所示:
Option<FileInfo> fileOption = new("--output")
{
Required = true
};
如果所需选项具有默认值(通过 DefaultValueFactory
属性指定),则无需在命令行上指定该选项。 在这种情况下,默认值提供所需的选项值。
论据
参数是可以传递给命令的未命名参数。 以下示例演示命令的参数 build
。
dotnet build myapp.csproj
^----------^
配置参数时,可以指定参数名称(它不用于分析,但可用于按名称获取分析值或显示帮助)和类型:
Argument<int> delayArgument = new("delay")
{
Description = "An argument that is parsed as an int.",
DefaultValueFactory = parseResult => 42
};
Argument<string> messageArgument = new("message")
{
Description = "An argument that is parsed as a string."
};
RootCommand rootCommand = new();
rootCommand.Arguments.Add(delayArgument);
rootCommand.Arguments.Add(messageArgument);
默认值
如果未显式提供任何参数,则参数和选项可以具有适用的默认值。 例如,许多选项是隐式的布尔参数,默认情况下,当选项名称出现在命令行中时,其值为 true
。 以下命令行示例等效:
dotnet tool update dotnet-suggest --global
^------^
dotnet tool update dotnet-suggest --global true
^-----------^
在没有默认值的情况下定义的参数被视为必需参数。
分析错误
选项和参数具有预期类型,当无法分析值时,将生成错误。 例如,以下命令会出错,因为“静默”不是--verbosity
的有效值之一:
dotnet build --verbosity silent
Option<string> verbosityOption = new("--verbosity", "-v")
{
Description = "Set the verbosity level.",
};
verbosityOption.AcceptOnlyFromAmong("quiet", "minimal", "normal", "detailed", "diagnostic");
RootCommand rootCommand = new() { verbosityOption };
ParseResult parseResult = rootCommand.Parse(args);
foreach (ParseError parseError in parseResult.Errors)
{
Console.WriteLine(parseError.Message);
}
Argument 'silent' not recognized. Must be one of:
'quiet'
'minimal'
'normal'
'detailed'
'diagnostic'
对于可以提供多少个值,自变量也是有预期的。 有关自变量 arity 的部分中提供了相关示例。
选项和自变量的顺序
可以在命令行中先提供选项再提供参数,或先提供参数再提供选项。 以下命令等效:
dotnet add package System.CommandLine --prerelease
dotnet add package --prerelease System.CommandLine
可以按任意顺序指定选项。 以下命令等效:
dotnet add package System.CommandLine --prerelease --no-restore --source https://api.nuget.org/v3/index.json
dotnet add package System.CommandLine --source https://api.nuget.org/v3/index.json --no-restore --prerelease
当有多个参数时,顺序确实很重要。 以下命令不等效;它们因值的顺序而异,这可能会导致不同的结果:
myapp argument1 argument2
myapp argument2 argument1
别名
在 POSIX 和 Windows 中,某些命令和选项都有别名很常见。 这些通常是更易于键入的短形式。 别名还可用于其他目的,例如 模拟不区分大小 写,并支持单词的备用拼写。
POSIX 短格式通常具有一个前导连字符,后跟一个字符。 以下命令等效:
dotnet build --verbosity quiet
dotnet build -v quiet
GNU 标准建议自动别名。 也就是说,您可以输入长格式命令或选项名称的任意部分,它会被接受。 此行为将使以下命令行等效:
dotnet publish --output ./publish
dotnet publish --outpu ./publish
dotnet publish --outp ./publish
dotnet publish --out ./publish
dotnet publish --ou ./publish
dotnet publish --o ./publish
System.CommandLine
不支持自动别名。 必须显式指定每个别名。 命令和选项都公开属性 Aliases
。
Option
具有接受别名作为参数的构造函数,因此可以在单个行中定义具有多个别名的选项:
Option<bool> helpOption = new("--help", ["-h", "/h", "-?", "/?"]);
Command command = new("serialize") { helpOption };
command.Aliases.Add("serialise");
建议尽量减少定义的选项别名数,并避免具体定义某些别名。 有关详细信息,请参阅 短格式别名。
事例敏感性
默认情况下,根据 POSIX 约定,命令和选项名称和别名区分大小写,并 System.CommandLine
遵循此约定。 如果你希望 CLI 不区分大小写,请为各种大小写备选项定义别名。 例如, --additional-probing-path
可能具有别名 --Additional-Probing-Path
和 --ADDITIONAL-PROBING-PATH
。
在某些命令行工具中,大小写上的差异会导致功能上的差异。 例如,git clean -X
的行为方式不同于 git clean -x
。 .NET CLI 全小写。
区分大小写不适用于基于枚举的选项的自变量值。 无论大小写如何,枚举名称都会匹配。
--
令牌
POSIX 约定会将双短划线 (--
) 令牌解释为转义机制。 双划线标记后面的所有内容都解释为命令的参数。 此功能可用于提交类似于选项的参数,因为它阻止将它们解释为选项。
假设 myapp 采用一个message
参数,并且希望其message
--interactive
值为 。 以下命令行可能会提供意外的结果。
myapp --interactive
如果myapp
没有--interactive
选项,--interactive
令牌将解释为参数。 但是,如果应用确实有一个选项 --interactive
,则此输入将解释为引用该选项。
以下命令行使用双划线标记将参数的值 message
设置为“--interactive”:
myapp -- --interactive
^^
System.CommandLine
支持此双短划线功能。
选项-自变量分隔符
System.CommandLine
允许使用空格、“=”或“:”作为选项名称与其参数之间的分隔符。 例如,以下命令等效:
dotnet build -v quiet
dotnet build -v=quiet
dotnet build -v:quiet
POSIX 约定允许在指定单字符选项别名时省略分隔符。 例如,以下命令等效:
myapp -vquiet
myapp -v quiet
System.CommandLine 默认情况下支持此语法。
自变量 arity
选项或命令参数的 arity 是指定该选项或命令时可以传递的值数。
Arity 以最小值和最大值表示,如下表所示:
最小值 | 麦克斯 | 示例有效性 | 示例: |
---|---|---|---|
0 | 0 | 有效: | --文件 |
无效: | --file a.json | ||
无效: | --file a.json --file b.json | ||
0 | 1 | 有效: | --标志 |
有效: | --flag true | ||
有效: | --flag false | ||
无效: | --flag false --flag false | ||
1 | 1 | 有效: | --file a.json |
无效: | --文件 | ||
无效: | --file a.json --file b.json | ||
0 | n | 有效: | --文件 |
有效: | --file a.json | ||
有效: | --file a.json --file b.json | ||
1 | n | 有效: | --file a.json |
有效: | --file a.json b.json | ||
无效: | --文件 |
System.CommandLine
使用 System.CommandLine.ArgumentArity
结构来定义 arity,具有以下值:
-
System.CommandLine.ArgumentArity.Zero
- 不允许任何值。 -
System.CommandLine.ArgumentArity.ZeroOrOne
- 可能有一个值,可能没有值。 -
System.CommandLine.ArgumentArity.ExactlyOne
- 必须有一个值。 -
System.CommandLine.ArgumentArity.ZeroOrMore
- 可能具有一个值、多个值或没有值。 -
System.CommandLine.ArgumentArity.OneOrMore
- 可能有多个值,必须至少有一个值。
可以使用属性 Arity
显式设置 arity,但在大多数情况下不需要。
System.CommandLine
根据参数类型自动确定参数 arity:
参数类型 | 默认 arity |
---|---|
Boolean |
ArgumentArity.ZeroOrOne |
集合类型 | ArgumentArity.ZeroOrMore |
其他 | ArgumentArity.ExactlyOne |
选项替代
如果 arity 最大值为 1, System.CommandLine
仍可配置为接受一个选项的多个实例。 在这种情况下,重复选项的最后一个实例将覆盖任何早期实例。 在以下示例中,值 2 将传递给 myapp
命令。
myapp --delay 3 --message example --delay 2
多个参数
默认情况下,调用命令时,可以重复选项名称,为具有大于一个最大 arity 的选项指定多个参数。
myapp --items one --items two --items three
若要允许多个参数而不重复选项名称,请设置为 System.CommandLine.Option.AllowMultipleArgumentsPerToken
true
。 此设置允许你输入以下命令行。
myapp --items one two three
如果最大参数 arity 为 1,则相同的设置将产生不同的效果。 它允许重复某个选项,但只采用行上的最后一个值。 在以下示例中,该值 three
将传递给应用。
myapp --item one --item two --item three
选项捆绑
POSIX 建议支持合并单字符选项,也称为叠加。 捆绑选项是单个连字符前缀后一起指定的单字符选项别名。 只有最后一个选项可以指定参数。 例如,以下命令行是等效的:
git clean -f -d -x
git clean -fdx
如果在选项捆绑后提供参数,则它适用于捆绑包中的最后一个选项。 以下命令行是等效的:
myapp -a -b -c arg
myapp -abc arg
在此示例中的这两个变体中,参数 arg
将仅适用于该选项 -c
。
布尔选项(标志)
如果为具有true
参数的选项传递false
或bool
,则会按预期对其进行分析。 参数类型为 bool
的选项通常不需要指定参数。 布尔选项(有时称为“标记”)的 arity 通常为 System.CommandLine.ArgumentArity.ZeroOrOne
。 在命令行中,当选项名称出现时且其后没有参数,默认值为true
。 命令行输入中缺少选项名称会导致值为false
。
myapp
如果命令输出名为--interactive
布尔选项的值,则以下输入将创建以下输出:
myapp
myapp --interactive
myapp --interactive false
myapp --interactive true
False
True
False
True
版本选项
基于System.CommandLine
构建的应用会在使用与根命令一起使用的--version
选项时自动提供版本号。 例如:
dotnet --version
6.0.100
响应文件
响应文件是包含命令行应用的一组令牌的文件。 响应文件是System.CommandLine
的一项功能,在两种场景中非常有用:
- 通过指定超过终端字符限制的输入来调用命令行应用。
- 重复调用同一命令而无需重新输入整个行。
若要使用响应文件,请在要插入命令、选项和参数的行中输入以符号为前缀 @
的文件名。
.rsp 文件扩展名是一种常见的约定,但你可以使用任何文件扩展名。
以下行等效:
dotnet build --no-restore --output ./build-output/
dotnet @sample1.rsp
dotnet build @sample2.rsp --output ./build-output/
sample1.rsp 的内容:
build
--no-restore
--output
./build-output/
sample2.rsp 的内容:
--no-restore
以下是用于确定如何解释响应文件中文本的语法规则:
- 标记由空格分隔。 包含早安的线条被视为两个标记,“好”和“早上!”。
- 括在引号中的多个令牌被解释为单个标记。 包含“早安!”的行被视为一个标记,即早安!
- 符号和行尾之间的
#
任何文本都被视为注释并忽略。 - 以
@
为前缀的令牌可以引用其他响应文件。 - 响应文件可以包含多行文本。 这些行是串接的,并被解释为一系列标记。
指令
System.CommandLine
引入了一个名为由类型表示的 指令 的 System.CommandLine.Directive
语法元素。 指令 [diagram]
是一个示例。 在应用名称后面包含 [diagram]
时, System.CommandLine
显示分析结果的关系图,而不是调用命令行应用:
dotnet [diagram] build --no-restore --output ./build-output/
^-----^
[ dotnet [ build [ --no-restore <True> ] [ --output <./build-output/> ] ] ]
指令的目的是提供跨命令行应用可应用的交叉功能。 由于指令在语法上与应用自己的语法不同,因此它们可以提供跨应用的功能。
指令必须符合以下语法规则:
- 它是命令行上的令牌,该令牌位于应用的名称之后,但在任何子命令或选项之前。
- 它被括在方括号中。
- 它不包含空格。
忽略无法识别的指令,而不会导致分析错误。
指令可以包含一个参数,该参数与指令名称之间用冒号分隔。
以下指令是内置的:
[diagram]
指令
用户和开发人员都可能会发现,了解应用如何解释给定输入会很有用。 应用的默认功能 System.CommandLine
之一是 [diagram]
指令,它允许预览分析命令输入的结果。 例如:
myapp [diagram] --delay not-an-int --interactive --file filename.txt extra
![ myapp [ --delay !<not-an-int> ] [ --interactive <True> ] [ --file <filename.txt> ] *[ --fgcolor <White> ] ] ???--> extra
在上面的示例中:
- 命令(
myapp
)、其子选项以及这些选项的参数使用方括号进行分组。 - 对于选项结果
[ --delay !<not-an-int> ]
,!
表示解析错误。not-an-int
选项的值int
无法分析为预期类型。 该错误还通过!
标记在包含错误选项的命令之前:![ myapp...
。 - 对于选项结果
*[ --fgcolor <White> ]
,该选项未在命令行上指定,因此使用了配置的默认值。White
是此选项的有效值。 星号指示该值为默认值。 -
???-->
指向与应用的任何命令或选项不匹配的输入。
建议指令
该 [suggest]
指令允许在不知道确切命令时搜索命令。
dotnet [suggest] buil
build
build-server
msbuild