Picocli:是否可以在名称中定义带有 space 的选项?
Picocli: Is it possible to define options with a space in the name?
我用谷歌搜索了一下,还在 Whosebug 上搜索,当然还有 Picocli 文档,但没有找到任何解决方案。
我工作的公司在批处理程序中使用特殊格式的命令行参数:
-VAR ARGUMENT1=VALUE -VAR ARGUMENT2=VALUE2 -VAR BOOLEANARG=FALSE
(不要问我为什么用这种格式,我已经质疑过了,没有得到正确的答案。)
现在我想使用 Picocli 进行命令行解析。但是,我无法让它与我们使用的参数格式一起工作,因为 space 让 Picocli 认为这是两个独立的参数,因此它不会将它们识别为我定义的参数。
这显然行不通:
@CommandLine.Option( names = { "-VAR BOOLEANARG" } )
boolean booleanarg = true;
使用 -VAR BOOLEANARG=FALSE 调用程序不会有任何效果。
有没有办法自定义那些包含space的特殊选项名称?或者我该怎么做?我也不允许将多个参数作为参数折叠到一个 -VAR 选项中。
非常感谢您的帮助。
谢谢并致以最诚挚的问候,
罗莎
解决方案 1:地图选项
最简单的解决方案是将 -VAR
设为 Map option。这可能看起来像这样:
@Command(separator = " ")
class Simple implements Runnable {
enum MyOption {ARGUMENT1, OTHERARG, BOOLEANARG}
@Option(names = "-VAR",
description = "Variable options. Valid keys: ${COMPLETION-CANDIDATES}.")
Map<MyOption, String> options;
@Override
public void run() {
// business logic here
}
public static void main(String[] args) {
new CommandLine(new Simple()).execute(args);
}
}
此示例的用法帮助如下所示:
Usage: <main class> [-VAR <MyOption=String>]...
-VAR <MyOption=String>
Variable options. Valid keys: ARGUMENT1, OTHERARG, BOOLEANARG.
请注意,使用此解决方案,所有值都将具有相同的类型(本例中为 String
),您可能需要转换为所需的类型(boolean
、int
, 其他...) 在应用程序中。
但是,考虑到您 post 中的这句话,这可能是不可接受的:
I also am not allowed to collapse multiple arguments as parameters into one -VAR option.
解决方案 2:参数组
替代方案的一个想法是使用 argument groups:我们可以将 ARGUMENT1
、OTHERARG
和 BOOLEANARG
分开的选项,然后将它们放在一个组中它们 必须 前面有 -VAR
选项。
生成的使用帮助如下所示:
Usage: group-demo [-VAR (ARGUMENT1=<arg1> | OTHERARG=<otherValue> |
BOOLEANARG=<bool>)]... [-hV]
-VAR Option prefix. Must be followed by one of
ARGUMENT1, OTHERARG or BOOLEANARG
ARGUMENT1=<arg1> An arg. Must be preceded by -VAR.
OTHERARG=<otherValue> Another arg. Must be preceded by -VAR.
BOOLEANARG=<bool> A boolean arg. Must be preceded by -VAR.
-h, --help Show this help message and exit.
-V, --version Print version information and exit.
实现可能如下所示:
@Command(name = "group-demo", mixinStandardHelpOptions = true,
sortOptions = false)
class UsingGroups implements Runnable {
static class MyGroup {
@Option(names = "-VAR", required = true,
description = "Option prefix. Must be followed by one of ARGUMENT1, OTHERARG or BOOLEANARG")
boolean ignored;
static class InnerGroup {
@Option(names = "ARGUMENT1", description = "An arg. Must be preceded by -VAR.")
String arg1;
@Option(names = "OTHERARG", description = "Another arg. Must be preceded by -VAR.")
String otherValue;
@Option(names = "BOOLEANARG", arity = "1",
description = "A boolean arg. Must be preceded by -VAR.")
Boolean bool;
}
// exclusive: only one of these options can follow a -VAR option
// multiplicity=1: InnerGroup must occur once
@ArgGroup(multiplicity = "1", exclusive = true)
InnerGroup inner;
}
// non-exclusive means co-occurring, so if -VAR is specified,
// then it must be followed by one of the InnerGroup options
@ArgGroup(multiplicity = "0..*", exclusive = false)
List<MyGroup> groupOccurrences;
@Override
public void run() {
// business logic here
System.out.printf("You specified %d -VAR options.%n", groupOccurrences.size());
for (MyGroup group : groupOccurrences) {
System.out.printf("ARGUMENT1=%s, ARGUMENT2=%s, BOOLEANARG=%s%n",
group.inner.arg1, group.inner.arg2, group.inner.arg3);
}
}
public static void main(String[] args) {
new CommandLine(new UsingGroups()).execute(args);
}
}
然后,调用 java UsingGroups -VAR ARGUMENT1=abc -VAR BOOLEANARG=true
得到:
You specified 2 -VAR options.
ARGUMENT1=abc, OTHERARG=null, BOOLEANARG=null
ARGUMENT1=null, OTHERARG=null, BOOLEANARG=true
使用这种方法,每次最终用户指定 -VAR
时,您都会得到一个 MyGroup
对象。这个 MyGroup
对象有一个 InnerGroup
,它有很多字段,除了一个 外,其他字段都是 null
。只有用户指定的字段才会是非null
。这是这种方法的缺点:在应用程序中,您需要检查所有字段以找到用户指定的非 null
字段。好处是通过为 @Option
-注释字段选择正确的类型,值将自动转换为目标类型。
我用谷歌搜索了一下,还在 Whosebug 上搜索,当然还有 Picocli 文档,但没有找到任何解决方案。
我工作的公司在批处理程序中使用特殊格式的命令行参数:
-VAR ARGUMENT1=VALUE -VAR ARGUMENT2=VALUE2 -VAR BOOLEANARG=FALSE
(不要问我为什么用这种格式,我已经质疑过了,没有得到正确的答案。) 现在我想使用 Picocli 进行命令行解析。但是,我无法让它与我们使用的参数格式一起工作,因为 space 让 Picocli 认为这是两个独立的参数,因此它不会将它们识别为我定义的参数。
这显然行不通:
@CommandLine.Option( names = { "-VAR BOOLEANARG" } )
boolean booleanarg = true;
使用 -VAR BOOLEANARG=FALSE 调用程序不会有任何效果。
有没有办法自定义那些包含space的特殊选项名称?或者我该怎么做?我也不允许将多个参数作为参数折叠到一个 -VAR 选项中。
非常感谢您的帮助。 谢谢并致以最诚挚的问候, 罗莎
解决方案 1:地图选项
最简单的解决方案是将 -VAR
设为 Map option。这可能看起来像这样:
@Command(separator = " ")
class Simple implements Runnable {
enum MyOption {ARGUMENT1, OTHERARG, BOOLEANARG}
@Option(names = "-VAR",
description = "Variable options. Valid keys: ${COMPLETION-CANDIDATES}.")
Map<MyOption, String> options;
@Override
public void run() {
// business logic here
}
public static void main(String[] args) {
new CommandLine(new Simple()).execute(args);
}
}
此示例的用法帮助如下所示:
Usage: <main class> [-VAR <MyOption=String>]...
-VAR <MyOption=String>
Variable options. Valid keys: ARGUMENT1, OTHERARG, BOOLEANARG.
请注意,使用此解决方案,所有值都将具有相同的类型(本例中为 String
),您可能需要转换为所需的类型(boolean
、int
, 其他...) 在应用程序中。
但是,考虑到您 post 中的这句话,这可能是不可接受的:
I also am not allowed to collapse multiple arguments as parameters into one -VAR option.
解决方案 2:参数组
替代方案的一个想法是使用 argument groups:我们可以将 ARGUMENT1
、OTHERARG
和 BOOLEANARG
分开的选项,然后将它们放在一个组中它们 必须 前面有 -VAR
选项。
生成的使用帮助如下所示:
Usage: group-demo [-VAR (ARGUMENT1=<arg1> | OTHERARG=<otherValue> |
BOOLEANARG=<bool>)]... [-hV]
-VAR Option prefix. Must be followed by one of
ARGUMENT1, OTHERARG or BOOLEANARG
ARGUMENT1=<arg1> An arg. Must be preceded by -VAR.
OTHERARG=<otherValue> Another arg. Must be preceded by -VAR.
BOOLEANARG=<bool> A boolean arg. Must be preceded by -VAR.
-h, --help Show this help message and exit.
-V, --version Print version information and exit.
实现可能如下所示:
@Command(name = "group-demo", mixinStandardHelpOptions = true,
sortOptions = false)
class UsingGroups implements Runnable {
static class MyGroup {
@Option(names = "-VAR", required = true,
description = "Option prefix. Must be followed by one of ARGUMENT1, OTHERARG or BOOLEANARG")
boolean ignored;
static class InnerGroup {
@Option(names = "ARGUMENT1", description = "An arg. Must be preceded by -VAR.")
String arg1;
@Option(names = "OTHERARG", description = "Another arg. Must be preceded by -VAR.")
String otherValue;
@Option(names = "BOOLEANARG", arity = "1",
description = "A boolean arg. Must be preceded by -VAR.")
Boolean bool;
}
// exclusive: only one of these options can follow a -VAR option
// multiplicity=1: InnerGroup must occur once
@ArgGroup(multiplicity = "1", exclusive = true)
InnerGroup inner;
}
// non-exclusive means co-occurring, so if -VAR is specified,
// then it must be followed by one of the InnerGroup options
@ArgGroup(multiplicity = "0..*", exclusive = false)
List<MyGroup> groupOccurrences;
@Override
public void run() {
// business logic here
System.out.printf("You specified %d -VAR options.%n", groupOccurrences.size());
for (MyGroup group : groupOccurrences) {
System.out.printf("ARGUMENT1=%s, ARGUMENT2=%s, BOOLEANARG=%s%n",
group.inner.arg1, group.inner.arg2, group.inner.arg3);
}
}
public static void main(String[] args) {
new CommandLine(new UsingGroups()).execute(args);
}
}
然后,调用 java UsingGroups -VAR ARGUMENT1=abc -VAR BOOLEANARG=true
得到:
You specified 2 -VAR options.
ARGUMENT1=abc, OTHERARG=null, BOOLEANARG=null
ARGUMENT1=null, OTHERARG=null, BOOLEANARG=true
使用这种方法,每次最终用户指定 -VAR
时,您都会得到一个 MyGroup
对象。这个 MyGroup
对象有一个 InnerGroup
,它有很多字段,除了一个 外,其他字段都是 null
。只有用户指定的字段才会是非null
。这是这种方法的缺点:在应用程序中,您需要检查所有字段以找到用户指定的非 null
字段。好处是通过为 @Option
-注释字段选择正确的类型,值将自动转换为目标类型。