预先悲伤的答案
它不会帮助你(不像你期望的那样可靠和可靠)。
这就是为什么。
虚拟“POSIX shell”无法解决的一个大问题是标准中措辞模棱两可或根本没有解决的问题,因此 shell 可以以不同的方式实现事物,同时仍然遵守标准。
以这两个关于管道的例子为例,其中第一个是众所周知的:
示例 1 - 范围界定
$ ksh -c 'printf "foo" | read s; echo "[${s}]"'
[foo]
$ bash -c 'printf "foo" | read s; echo "[${s}]"'
[]
ksh
在当前 shell 中执行管道的最后一个命令,而bash
在子 shell 中执行所有命令 - 包括最后一个命令。bash 4
引入了lastpipe
使其行为类似于的选项ksh
:
$ bash -c 'shopt -s lastpipe; printf "foo" | read s; echo "[${s}]"'
[foo]
所有这些都是(有争议的)根据标准:
此外,多命令管道的每个命令都处于子shell环境中;然而,作为扩展,管道中的任何或所有命令都可以在当前环境中执行。
我不是 100% 确定他们对extension的含义,但是根据文档中的其他示例,这并不意味着 shell 必须提供一种在行为之间切换的方法,而只是说它可以,如果它愿意的话,实现一些东西以这种“扩展方式”。其他人对此的理解不同,并争论这种ksh
行为不符合标准,我明白为什么。措辞不仅不吉利,而且一开始就允许这样做也不是一个好主意。
在实践中,哪种行为是正确的并不重要,因为它们是“”“两个大壳”“”,人们会认为如果你不使用他们的扩展并且只使用它应该工作的符合 POSIX 的代码要么,但事实是,如果您依赖上面提到的一种或另一种行为,您的脚本可能会以可怕的方式中断。
示例 2 - 重定向
这是我几天前才了解到的,请在此处查看我的答案:
foo | bar 2>./qux | quux
常识和POLA告诉我,当命中下一行代码时,两者都quux
应该bar
已经完成运行,这意味着文件./qux
已完全填充。对?不。
POSIX指出
如果管道不在后台(参见异步列表),shell 将等待管道中指定的最后一个命令完成,也可能等待所有命令完成。)
可以(!)等待所有命令完成!哇!
bash等待:
shell 在返回值之前等待管道中的所有命令终止。
但ksh没有:
每个命令(可能是最后一个命令除外)都作为单独的进程运行;shell 等待最后一个命令终止。
因此,如果您在管道之间使用重定向,请确保您知道自己在做什么,因为这会受到不同的处理,并且可能会在极端情况下严重中断,具体取决于您的代码。
我可以举另一个与管道无关的例子,但我希望这两个就足够了。
结论
有一个标准是好的,不断修改它更好,坚持它是很好的。但是,如果标准由于模棱两可或许可而失败,事情仍然会意外地破坏,实际上使标准的有用性无效。
这在实践中意味着,除了编写“符合 POSIX 的”代码之外,您还需要思考并知道您正在做什么以防止某些事情发生。
话虽如此,根据其手册页,一个尚未提及的 shellposh
据说是 POSIX 加上比现有更少的扩展dash
(主要echo -n
是关键字):local
BUGS
Any bugs in posh should be reported via the Debian BTS.
Legitimate bugs are inconsistencies between manpage and behavior,
and inconsistencies between behavior and Debian policy
(currently SUSv3 compliance with the following exceptions:
echo -n, binary -a and -o to test, local scoping).
YMMV。