`if $cmd 究竟如何;然后 $cmd ; fi` 与 `$cmd && $cmd` 不同吗?

mik*_*erv 5 shell shell-script posix

在回答另一个非常好的问题时,我做出了以下断言:

根据我对 POSIX 规范的阅读,从解析的角度来看,使用一个或另一个没有区别。

POSIX 指定&&||列表是复合命令,这意味着在执行组成的简单命令之前必须读入和解析整个列表。POSIX 还规定,如果一个命令跟在一个和另一个具有 0 退出状态的命令之后,则该命令不得扩展||OR。当您考虑到&&||保留字后面的命令很容易被另一个分组时,{ command || ( command ; list) ; }就会使&&||或 列出自己的复合命令的每个分支。

但是 POSIX 也以这种方式指定if...;then...;else...fi构造的每个分支都是它自己的复合命令

if compound-list
then
    compound-list
[elif compound-list
then
    compound-list] ...
[else
    compound-list]
fi
Run Code Online (Sandbox Code Playgroud)

执行if 复合列表;如果它的exit状态为零,则then 复合列表将被执行并且命令将完成......

正是这个规范表明 athen...else...保留字后面的字符串本身就是复合命令,而不仅仅是简单的命令,这意味着 shell 的解析器必须用命令和分隔符来表示它们才能正确操作。

所以基本上,then ' '出于同样的原因不起作用:

function()
sh: line 2: syntax error: unexpected end of file 
Run Code Online (Sandbox Code Playgroud)

...没有 - 它没有任何意义。

我知道...

[ -e doesntexist ] && $((i=1)) ; echo $i
Run Code Online (Sandbox Code Playgroud)

...将短路任何副作用,并由于\n我在回答中指出的规范而仅导致ewline。的结果...

if [ -e doesntexist ] 
    then $((i=1))
fi
echo $i
Run Code Online (Sandbox Code Playgroud)

……一模一样。

但老实说if...fi,我很少使用,以至于我不确定我是否误读了什么,所以当我收到一条评论表明我的解释不正确,如果我对此事有进一步的问题,我只需要问我就删除了答案来代替这个问题:我怎么弄错了——它们有什么不同?

Gil*_*il' 4

&&只有简单的情况才可以用和 来表示||。该if结构更为通用。if CONDITION; then FOO; fi相当于CONDITION && FOO(假设必要时正确使用大括号来分隔块),但是只要有一个else(或elif),一般情况下就不再可能了。

\n\n
if CONDITION; then FOO; else BAR; fi\n
Run Code Online (Sandbox Code Playgroud)\n\n

不等于

\n\n
CONDITION && FOO || BAR\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果CONDITION为 true,则两个构造都执行FOO。如果FOO为 false,则if构造跳过BAR,而&& \xe2\x80\xa6 ||构造执行BAR

\n\n

不,你不能用 来解决这个问题CONDITION && { FOO; true; } || BAR。这使得复合命令在CONDITION为 true 且FOO为 false 时返回 true,而if CONDITION; then FOO; else BAR; fi在这种情况下返回 false。

\n\n

这是语义上的差异。此外,还有可读性:&&and的嵌套使用||的嵌套使用很快就变得难以破译。我不建议在同一个命令中使用两者,事实上 \xe2\x80\x94 特别是考虑到这两个运算符在 shell 中具有相同的优先级,而它们在 C 和大多数其他 C 语言(包括 Perl)中具有不同的优先级和红宝石)。

\n