我正在使用JCommander(版本1.32)来解析传递给java应用程序的命令行参数(让我们称之为app
)。我遇到的问题是我需要传递的其中一个参数以@
开头,可以看出here @
有一个特殊的语法。因此,使用app @arg
调用应用程序失败并显示
无法读取文件arg:java.io.FileNotFoundException:arg(没有这样的文件或目录)。
通过阅读这些信息,我尝试将我的参数放在一个文件中,但显然“@语法”是递归的,因此,即使我将@arg
放在一个文件中,我的程序也会因同样的错误而失败。
有没有办法将以@
开头的参数传递给使用jcommander的程序?有没有办法禁用@
语法?
答案 0 :(得分:5)
由于OP和我之间的聊天讨论,我们得出以下结论:
JCommander调用自身,作为解析命令的方式的一部分 - 每个子命令结构都有自己的参数定义。
在顶层,它展开@ -parameter并创建一个包含文件内容的新参数列表。
然后,当它自己调用时,它再次解析该参数列表,因此再次扩展以@
开头的任何参数。
幸运的是,它似乎只会这样做一次,所以它不是完全递归的。因此,任何想要传递以@
开头的参数的人的解决方案是使用两个间接。也就是说,创建两个文件:
FILE1.TXT
@file2.txt
FILE2.TXT
@actualparameter
然后在命令行上使用@file1.txt
。
所以这是一种可行的解决方法。就个人而言,我对创建这样的额外文件并不太满意,我建议使用其他三种解决方案之一:
@
机制或让原作者自己这样做。@
开头的任何参数,然后在需要使用参数值时删除该字符。至少这不会创建两个额外的文件。根据对this pull request on Jcommander's github的评论,有一种新方法可以禁用@
符号的处理。 E.g。
JCommander jc = new JCommander(params);
jc.setExpandAmpersat(false);
从1.54版开始添加了该方法。
答案 1 :(得分:0)
完全禁用该功能
您可以通过以下方式禁用 @
参数的扩展:
jc.setExpandAmpersat(false)
(如 in this answer 所述)jc.setExpandAtSign(false)
(在某些版本中)builder上也有相应的选项
对文件使用间接
如果您在命令行解析中绝对依赖 @
,并且您希望您的用户需要传递以 @
开头的文件名或其他参数,您可以询问他们使用额外的文件使用间接。
例如将文件名 @foo
传递给 --file
,将 @foo
写在文本文件的单行上,然后通过 --file @textfile
传递该文件。扩展不是递归的。
这并不适用于所有情况。但你可以说服自己这是可以接受的。
以@开头的转义参数
应该注意的是,JCommander 仅在 start 参数时扩展 @
。知道这一点,并假设您已经对程序中的参数解析有了一些控制,您可以单独保留 JCommander 默认行为,但要求用户使用转义字符前缀明确禁用每个参数。
例如您可以建立一个约定,如果用户希望在命令行上传递文件名“@foo”(或者说,twitter 句柄),他们可以使用反斜杠或空格作为前缀:--file " @foo"
或 {{ 1}}。这将阻止 JCommander 的自动扩展,但随后您的代码需要在进一步处理参数之前检测并去除该额外字符。