混淆&&和||的使用 经营者


92

我浏览了一个/etc/rc.d/init.d/sendmail文件(我知道这几乎没用过,但是我正在学习考试),并且对&&||操作符有些困惑。我已经阅读了可以在诸如以下语句中使用它们的地方:

if [ test1 ] && [ test2 ]; then
     echo "both tests are true"
elif [ test1 ] || [ test2 ]; then
     echo "one test is true"
fi

但是,此脚本显示单行语句,例如:

[ -z "$SMQUEUE" ] && SMQUEUE="QUEUE"
[ -f /usr/sbin/sendmail ] || exit 0

这些似乎正在使用&&and ||运算符基于测试得出响应,但是我无法从这些运算符的这种特殊用法中提取文档。谁能解释在特定情况下这些工具的作用?

Answers:


140

&&仅当左侧的退出状态为零(即为true)时,才会评估的右侧。||相反:只有在左侧出口状态为非零(即false)时,它才会评估右侧。

您可以考虑[ ... ]将其作为具有返回值的程序。如果内部测试的结果为true,则返回零;否则,返回零。否则返回非零。

例子:

$ false && echo howdy!

$ true && echo howdy!
howdy!
$ true || echo howdy!

$ false || echo howdy!
howdy!

额外说明:

如果这样做which [,您可能会看到[实际上确实指向一个程序!但是,通常它实际上不是在脚本中运行的那个。运行type [以查看实际运行的内容。如果您想尝试使用该程序,只需给出完整的路径,如下所示:/bin/[ 1 = 1


6
当您看到“ X或Y”时,您将测试X。如果是,则已经知道“ X或Y”的答案(是),因此无需测试Y。如果是,则您不知道X。答案为“ X或Y”,因此您确实需要测试Y。看到“ X和Y”时,您将测试X。如果它为假,则您已经知道了“ X和Y”的答案(它为假),因此无需测试Y。如果X为true,那么您确实需要测试Y以查看“ X and Y”是否为true。
David Schwartz

2
而不是“如果左侧返回零”,我会写“如果左侧命令的退出状态为零”。我发现“返回”有点模棱两可,因为输出和退出状态都可以视为“返回值”
glenn jackman 2011年

您不仅可以“ 考虑 [ ... ]到是一个程序”,在许多情况下,它。通常在文件/bin/[或中/usr/bin/[
LS

5
C程序员会发现这个超级混乱。那里0表示错误...而在shellscript中0表示正确...
Calmarius

你可以提到另外一个是test代替if[。而if [if test似乎与穿插[,并test没有明显的情由。test有时会出现,例如在config.site上的Fedora x86_64上的供应商库

58

这是我的备忘单:

  • “ A; B”运行A,然后运行B,无论A是否成功
  • 如果A成功,则执行“ A && B”运行B
  • 如果A失败,请运行“ A || B”
  • “ A&”在后台运行A。

在运行的JavaScript中,有一些有趣的Lambda微积分并行操作(按顺序定义变量);“ left(又名true)” :(a => b => a)。“正确(又名假)” :(a => b => b)。“ A; B”“然后” (a => b => (() => b())(a()))。“ A && B”“如果没有(何时)” (a => b => a()(() => right)(b))。“ A || B”“否则,如果没有(除非)” (a => b => a()(b)(() => right))。“ a && b || c”“ ifThenElse” (a => b => c => (unless(when(a)(b))(c))())
德米特里(Dmitry)

1
请注意,在bash中,左边是类似0 /空字符串,右边是其他所有东西。
德米特里(Dmitry)

27

从上面扩展@ Shawn-j-Goff的答案,&&它是逻辑AND,并且||是逻辑OR。

请参阅《高级Bash脚本指南》的这一部分。链接中的某些内容供用户参考,如下所示。

&& AND

if [ $condition1 ] && [ $condition2 ]
#  Same as:  if [ $condition1 -a $condition2 ]
#  Returns true if both condition1 and condition2 hold true...

if [[ $condition1 && $condition2 ]]    # Also works.
#  Note that && operator not permitted inside brackets
#+ of [ ... ] construct.

|| 要么

if [ $condition1 ] || [ $condition2 ]
# Same as:  if [ $condition1 -o $condition2 ]
# Returns true if either condition1 or condition2 holds true...

if [[ $condition1 || $condition2 ]]    # Also works.
#  Note that || operator not permitted inside brackets
#+ of a [ ... ] construct.

10

根据我的经验,我使用&&和|| 将if语句减少到一行。

假设我们正在寻找一个名为/root/Sample.txt的文件,那么传统的迭代将在shell中如下所示:

if [ -f /root/Sample.txt ]
then
    echo "file found"
else
    echo "file not found"
fi

这6行可以简化为一行:

[[ -f /root/Sample.txt ]] && echo "file found" || echo "file not found"

当运行几次迭代以设置变量或创建文件等时,使用起来更容易,并且如果使用单行if函数,脚本看起来更流畅,唯一的缺点是从单个迭代中实现多个命令会变得更加困难。您可以利用功能。


这很酷。让我想起objc代码(a == b)?val = 1:val = 2;
GeneCode

我想在后台使用“&”运行进程时如何使用此命令?我收到了./someScript.sh & && echo 'ok' || echo 'ko'
Katie

3

有一个“捷径”的概念。

何时(expr1 && expr2)评估- expr2仅在exp1评估为“ true” 时才评估。这是因为两个expr1AND expr2都必须为真(expr1 && expr2)才能成立。如果expr1计算结果为“ false”,expr2则不会进行评估(快捷方式),因为(expr1 && expr2)已经是“ flase”。

请尝试以下操作-假设文件F1存在且文件F2不存在:

( [ -s F1 ] && echo "File Exists" )  # will print "File Exists" - no short cut
( [ -s F2 ] && echo "File Exists" )  # will NOT print "File Exists" - short cut

对于||(或)同样如此-但捷径相反。


4
该逻辑通常称为“短路”。我从未见过使用“捷径”这个词。我提到这一点是为了帮助查找参考。
LS

-1

Shawn J. Goff的答案中的示例是正确的,但解释却相反。请检查:

仅当左侧的退出状态为NONZERO时,才会评估&&的右侧。|| 相反:只有在左侧出口状态为零时,它才会评估右侧。


3
您知道,对于外壳,退出代码的计算结果为true,因此整个表达式中结果左侧的非零退出代码&&返回false
反模式

1
有人不批准您的修改,因为这不是您的答案。如果您认为某个答案不正确,则应该对其投下反对票,并可能发表评论;如果您认为需要更改,则应发表评论。编辑是为了纠正不会改变答案含义的语法,格式和拼写错误。
techraf

1
@countermode对不起,您是对的,我认为在Linux中零=假,非零=真(例如在C语言和许多其他语言/环境/平台中)。造成误解,我深表歉意。
Try2Help
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.