为什么可以省略选项和参数之间的空格?


16

例如:

xargs -n 1

是相同的

xargs -n1

但是,如果您查看手册页,该选项将列为-n max-args,这意味着应该保留该空间。缩写形式-n max-args没有任何意义。

其他许多Linux实用程序也会发生这种情况。

在Linux中这叫什么?是否所有实用程序都支持缩写形式(但切勿在手册页中对其进行文档化)?


1
12.1.2.a是历史的一部分;我发誓这里已经有一个很好的问题,但是我还没有找到。

2
@drewbenn您正在考虑的另一个问题可能是我的:unix.stackexchange.com/q/188046/41515

Answers:


12

当您编写代码的命令行解析位时,您可以指定哪些选项带有参数,哪些不带参数。例如,在接受一个-h选项(例如帮助)和一个-a应该带有参数的选项的shell脚本中,您可以执行

opt_h=0     # default value
opt_a=""

while getopts 'a:h' opt; do
    case $opt in
        h)  opt_h=1 ;;
        a)  opt_a="$OPTARG" ;;
    esac
done

echo "h: $opt_h"
echo "a: $opt_a"

a:h位显示“我希望解析两个选项-a-h,并且-a应该接受一个参数”(这是在:之后a告诉解析器-a接受一个参数)。

因此,在选项的结束位置,其值的起始位置以及此后的另一个位置的位置都没有任何歧义。

运行它:

$ bash test.sh -h -a hello
h: 1
a: hello

$ bash test.sh -h -ahello
h: 1
a: hello

$ bash test.sh -hahello
h: 1
a: hello

这就是为什么您大多数时候不应该编写自己的命令行解析器来解析选项的原因。

在此示例中,只有一种情况比较棘手。解析通常会在第一个非选项时停止,因此当您在命令行中看到类似于选项的内容时:

$ bash test.sh -a hello -world
test.sh: illegal option -- w
test.sh: illegal option -- o
test.sh: illegal option -- r
test.sh: illegal option -- l
test.sh: illegal option -- d
h: 0
a: hello

以下解决方案:

$ bash test.sh -a hello -- -world
h: 0
a: hello

--信号的命令行选项的结束,而-world位是留给程序为所欲为用(这是在位置变量之一)。

顺便说一句,就是如何删除文件名开头带有破折号的文件rm

编辑

用C调用getopt()(在中声明unistd.h)编写的实用程序,其工作方式几乎相同。事实上,我们都知道,该bash功能getopts可使用C库函数的调用来实现getopt()。Perl,Python和其他语言具有相似的命令行解析库,并且很有可能它们以相似的方式执行解析。

其中一些的getoptgetopt式的库函数也处理“长”选项。这些通常以双破折号(--)开头,并且带有参数的长选项通常在等号后才这样做,例如--block-size=SIZEdu实用程序[的某些实现]的选项(还允许-B SIZE指定相同的内容)。

编写手册的原因通常是在简短选项之间显示空格,而其参数可能是为了便于阅读。

编辑真正的旧工具,例如dd和和tar实用程序,在它们前面都带有短划线的选项。这纯粹是出于历史原因,并且是为了保持与依靠它们以这种方式工作的软件的兼容性。该tar实用程序最近获得了使用破折号进行选择的功能。BSD手册用于tar调用“捆绑标志”的旧选项。


在bash脚本中似乎易于实现此功能。但是我认为大多数实用程序都是用C编写的(然后编译为二进制文件)而不是bash。为什么这些实用程序实现此功能?
J.Joe

@ J.Joe因为他们调用getopt()(在中声明了unistd.h),所以执行相同的操作。
库桑兰达

2
是的,你是对的。参考。这也解决了另一个-a -b-ab
难题

1
标志的可选参数会产生歧义,因此无法将其组合(如果-a具有可选参数,-ab则与相同-a -b)。当遇到非标记时,GNU getopt不会停止标记处理:(默认情况下)相反,而是将标记重新排列到argv的前面。
ilkkachu

@ilkkachu感谢您的澄清。我可以稍后再更新我的答案。
库沙兰丹

4

xargs是POSIX实用程序之一。正如@drewbenn所评论的那样,POSIX记录了其大多数实用程序要匹配的选项解析行为getopt,并为其他实现提供了一些余地,如12.1实用程序参数语法所示

本节描述了标准实用程序的参数语法,并介绍了整个POSIX.1-2008使用的术语,用于描述由实用程序处理的参数。

在POSIX.1-2008中,使用特殊符号来描述实用程序参数的语法。除非另有说明否则所有实用程序描述都使用此符号,此示例对此进行了说明(请参见XCU 简单命令):

并与

建议所有将来的实用程序和应用程序都使用这些准则来增强用户的可移植性。某些历史实用程序无法更改(以避免破坏现有应用程序)的事实不应阻止此未来目标。

在POSIX(记住,这仅覆盖了最常用的实用工具),还有一些通过操作数这将是例外选项在其他公用事业无论是位置参数,或者参数特殊语法

POSIX允许可选的选项值:

选项参数以<blank>字符分开显示,与选项分开,除非选项参数包含在'['']'表示法中以表明它是可选的。

暂时,我不记得哪个POSIX实用程序使用了该功能。Ncurses程序ticinfocmp实用工具使用的功能级别的的-v(详细/调试)选项。

您询问的具体点在该段的其余部分中进行了详细说明,分几行。

在POSIX之前,ps接受的选项的某些实现没有前导连字符。POSIX描述未在实用程序描述或语法原理中提及:

除了POSIX之外,还有长选项实现(例如GNU getopt_longX Toolkit),使用多种方式将选项的值分离或结合到选项中。例如,可以使用标点符号:

--option=value
--option value

根据实现的不同,可能会/可能不会使用双破折号来区分长选项和短选项(getopt):lynx和X Toolkit使用一个破折号;例如,GNU getopt_long使用双破折号。同样,+可以使用a 表示选项被否定。

POSIX的描述似乎没有提到任何这些,但是您肯定会遇到它们。


-option=value认为是--option=value(长选项格式,两个破折号在开始的一个替代)?
J.Joe

一些旧版实用程序使用单破折号长选项(-option),但在新脚本和程序中不推荐使用。使用单破折号表示由getopt处理的简短选项。几乎所有新脚本和程序都使用双破折号长选项。许多还支持最常用的单破折号短期权等价物。长选项使脚本代码更易于自我记录,需要更少的注释。
DocSalvager '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.