处理/ bin/sh的参数中的' - ':POSIX vs Bash/Dash/FreeBSD的实现

Jér*_*gis 10 shell posix freebsd options

我想调用/ bin/sh,并使用-c选项传递命令'+ x',即执行名为'+ x'的程序,其名称以加号开头.

由于'+ x'被/ bin/sh解释为一个选项(具体来说,禁用'x'选项),因此必须阻止/ bin/sh将其解释为一个选项.根据我使用的/ bin/sh,我得到以下不同的结果:

(1)第一个变种:

/bin/sh -c -- +x
Run Code Online (Sandbox Code Playgroud)

在Linux上使用Dash和Bash:执行命令+ x.

使用FreeBSD的sh:执行命令 - 并设置+ x选项.

(2)第二种变体:

/bin/sh -c +x
Run Code Online (Sandbox Code Playgroud)

在Linux上使用Dash和Bash:设置了+ x选项,并且出现错误,因为选项-c缺少参数.

使用FreeBSD的sh:执行命令+ x.

(3)第三种变体:

/bin/sh -c - +x
Run Code Online (Sandbox Code Playgroud)

在Linux上使用Dash和Bash:执行+ x.

使用FreeBSD的sh:执行命令 - 并设置选项+ x.

(4)第四种变体:(按评论中的建议添加)

/bin/sh -c+x
Run Code Online (Sandbox Code Playgroud)

在Linux上使用Dash和Bash:无效/非法选项'+'

使用FreeBSD的sh:Bad -c选项


我的问题:POSIX开的是什么?

我在这里阅读POSIX规范:http: //pubs.opengroup.org/onlinepubs/9699919799/utilities/sh.html

引用它:"单个连字符应被视为第一个操作数,然后被忽略.如果' - '和" - "都作为参数给出,或者如果其他操作数在单个连字符之前,则结果是未定义的.

我不确定这句话是否也适用于'-c'之后的单个短划线.

那么,哪一个是正确的,Dash/Bash还是FreeBSD?或者,如果两者都是正确的,因为POSIX允许两者,如何可移植?

ric*_*ici 6

OP中已经出现了"Posix规定了什么"这一问题的答案.但Posix标准的重要特征并没有突显出来:-c选项不会引起争论.

你可以在概要中看到这个:

sh -c [-abCefhimnuvx] [-o option]... [+abCefhimnuvx] [+o option]...
      command_string [command_name [argument...]]
Run Code Online (Sandbox Code Playgroud)

什么-c旗做的是使该位置参数("操作数"),以不同的方式来解释.没有-c,它们被解释为[command_file [argument...]]:

sh [-abCefhimnuvx] [-o option]... [+abCefhimnuvx] [+o option]...
   [command_file [argument...]]
Run Code Online (Sandbox Code Playgroud)

顺便说一下,这就是为什么sh -c+x是一个错误.如果-c采用了一个论证,那么将论证包含在同一个词中是合法的.

那么,回答更具体的问题:

  1. Posix说"单个连字符应被视为第一个操作数,然后忽略......".这适用于-紧随其后的-c吗?

    答:是的,确实如此.-c是一个完整的选项,-因此是一个操作数.相比之下,-in -o -不会被视为操作数.(它将被视为无效的选项名称.)

  2. 哪一个是正确的,Dash/Bash还是FreeBSD?

    答:在这种情况下,Dash和Bash是Posix兼容的,而FreeBSD的sh则不是.FreeBSD的shell大大早于当前的Posix规范,我不相信它曾声称完全符合任何Posix规范.

  3. 如何可移植地用于sh运行名称以+?开头的命令?

    答:我认为以下内容适用于任何shell:

    sh -c " +x"
    
    Run Code Online (Sandbox Code Playgroud)

    " +x"会不会被视为一种选择,因为它不以启动+-,并sh -c导致被解析为一个shell命令的操作,所以开头的空白将被忽略.我刚才没有FreeBSD的副本ash,所以我欢迎更正.

    或者你可以使用一个简单的复合命令:

    sh -c "{ +x; }"
    
    Run Code Online (Sandbox Code Playgroud)

    可能最清楚(假设您正在使用的shell实现Posix标准内置command)是:

    sh -c "command +x"
    
    Run Code Online (Sandbox Code Playgroud)