在对另一个人的回答中非常好问题我做出以下断言:
根据我对 POSIX 规范的阅读,从解析的角度来看,使用其中之一并没有什么区别。
POSIX 指定&&||
列表是复合命令这意味着在执行组成的简单命令之前必须读入并解析整个列表。 POSIX还指定了一个命令不得扩大如果它跟随||OR
另一个具有 0 退出状态的命令。当您认为保留字后面的命令&&||
可以很容易地被另一个分组时{ command || ( command ; list) ; }
,请使 或 列表的每个分支都有&&||
自己的复合命令。
但 POSIX 还指定if...;then...;else...fi
构造的每个分支都有自己的复合命令这样:
if compound-list
then
compound-list
[elif compound-list
then
compound-list] ...
[else
compound-list]
fi
这
if
复合列表应予执行;如果其exit
状态为零,则then
复合列表将被执行并且命令将完成...
then...
正是这个规范使得or后面的字符串else...
保留字后面的字符串是复合命令以其自身的权利而不仅仅是简单的命令这意味着 shell 的解析器必须用命令和分隔符来表示它们才能正确运行。
所以基本上,then ' '
出于同样的原因不起作用:
function()
sh: line 2: syntax error: unexpected end of file
……不——这没有任何意义。
我知道...
[ -e doesntexist ] && $((i=1)) ; echo $i
...将短路任何副作用,并且\n
由于我在答案中指出的规范而仅导致一条 ewline 。的结果...
if [ -e doesntexist ]
then $((i=1))
fi
echo $i
……是一样的。
但老实说,我if...fi
很少使用,以至于我不确定我是否误读了某些内容,因此当我收到一条评论表明我的解释不正确,并且如果我对此事有进一步的问题时,我只需要问我就删除了答案来代替这个问题:我怎么弄错了——它们有什么不同?
答案1
只有简单的情况才可以用 和 来&&
表示||
。该if
结构更为通用。if CONDITION; then FOO; fi
相当于CONDITION && FOO
(假设必要时正确使用大括号来分隔块),但一旦出现else
(或elif
),一般情况下就不再可能了。
if CONDITION; then FOO; else BAR; fi
不等于
CONDITION && FOO || BAR
如果CONDITION
为 true,则两个构造都执行FOO
。如果FOO
为 false,则if
构造会跳过BAR
,而&& … ||
构造会执行BAR
。
不,你不能用 来解决这个问题CONDITION && { FOO; true; } || BAR
。这使得复合命令在CONDITION
为 true 且FOO
为 false 时返回 true,而if CONDITION; then FOO; else BAR; fi
在这种情况下返回 false。
这是语义上的差异。此外,还有可读性:&&
和的嵌套使用||
很快就变得难以破译。事实上,我不建议在同一个命令中使用这两个运算符 — 特别是考虑到这两个运算符在 shell 中具有相同的优先级,而它们在 C 和大多数其他 C 语言(包括 Perl 和 Ruby)中具有不同的优先级。
答案2
if testlist; then else ...fi
且testlist && thenlist || elselist
一般而言并不等价。不同之处在于,在构造中,恰好执行了和if
之一。在另一种情况下,它取决于(和可能的块)的退出代码。thenlist
elselist
thenlist
eliflist
因此,您必须true
在选定结果列表的末尾添加(例如),以便该列表具有与导致其执行的测试列表相同的退出代码。
if true; then
echo true
test -e doesntexist
else
echo false
fi
可以通过确定代码块的退出代码&&
来重写。||
代替
true && { echo true; test -e doesntexist; } || echo false
你需要
true && { echo true; test -e doesntexist; true; } || echo false
埃利夫
if test -e exists; then
echo true
elif test -e doesntexist
echo elif
else
echo false
fi
将会
test -e exists && { echo true; true; } ||
{ test -e doesntexist && { echo elif; true; } || echo false; }