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

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

在对另一个人的回答中非常好问题我做出以下断言:

根据我对 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 ...fitestlist && thenlist || elselist一般而言并不等价。不同之处在于,在构造中,恰好执行了和if之一。在另一种情况下,它取决于(和可能的块)的退出代码。thenlistelselistthenlisteliflist

因此,您必须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; }

相关内容