我想调用/ bin / sh,并使用-c选项传递命令'+ x',即执行名为'+ x'的程序,其名称以加号开头。
由于'+ x'被/ bin / sh解释为一个选项(具体来说,禁用'x'选项),必须阻止/ bin / sh将其解释为一个选项。根据我使用的/ bin / sh,我得到以下不同的结果:
(1)第一个变种:
/bin/sh -c -- +x
在Linux上使用Dash和Bash:执行命令+ x。
使用FreeBSD的sh:执行命令 - 并设置+ x选项。
(2)第二种变体:
/bin/sh -c +x
在Linux上使用Dash和Bash:设置了+ x选项,并且出现错误,因为选项-c缺少参数。
使用FreeBSD的sh:执行命令+ x。
(3)第三种变体:
/bin/sh -c - +x
在Linux上使用Dash和Bash:执行+ x。
使用FreeBSD的sh:执行命令 - 并设置选项+ x。
(4)第四种变体:(在评论中建议添加)
/bin/sh -c+x
在Linux上使用Dash和Bash:无效/非法选项'+'
使用FreeBSD的sh:Bad -c选项
我的问题:POSIX开的是什么?
我正在阅读这里的POSIX规范:http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sh.html
引用它:“单个连字符应被视为第一个操作数然后被忽略。如果' - '和” - “都作为参数给出,或者如果其他操作数在单个连字符之前,则结果是未定义的“。
我不确定该引用是否也适用于'-c'之后的单个短划线。
那么,哪一个是正确的,Dash / Bash还是FreeBSD?或者,如果两者都是正确的,因为POSIX允许两者,那么如何移植呢?
答案 0 :(得分:6)
OP中已经出现了“Posix规定的内容”这一问题的答案。但是Posix标准的重要特征没有突出显示: -c
选项不参与。
您可以在概要中看到:
sh -c [-abCefhimnuvx] [-o option]... [+abCefhimnuvx] [+o option]...
command_string [command_name [argument...]]
-c
标志的作用是使位置参数(“操作数”)以不同的方式解释。如果没有-c
,则会将其解释为[command_file [argument...]]
:
sh [-abCefhimnuvx] [-o option]... [+abCefhimnuvx] [+o option]...
[command_file [argument...]]
顺便说一下,这就是为什么sh -c+x
是错误的原因。如果-c
接受了论证,那么将参数包含在同一个单词中是合法的。
所以,回答更具体的问题:
Posix说“单个连字符应被视为第一个操作数,然后被忽略......”。这是否适用于紧随-
后的-c
?
-c
是一个完整的选项,因此-
是一个操作数。相比之下,-
中的-o -
不会被视为操作数。 (它将被视为无效的选项名称。) 哪一个是正确的,Dash / Bash还是FreeBSD?
答:在这种情况下,Dash和Bash是Posix兼容的,FreeBSD的sh不是。 FreeBSD的shell大大早于当前的Posix规范,我认为它并不认为它完全符合任何Posix规范。
如何移植sh
来运行名称以+
开头的命令?
答:我认为以下内容适用于任何shell:
sh -c " +x"
" +x"
不会被识别为选项,因为它不是以+
或-
开头,而sh -c
会导致操作数被解析为shell命令,因此将忽略前导空格。我现在没有FreeBSD ash
的副本,所以我欢迎更正。
或者您可以使用简单的复合命令:
sh -c "{ +x; }"
可能最清楚(假设您使用的shell实现了Posix标准内置command
):
sh -c "command +x"