bash 中的“foo && bar || baz”与“if foo; then bar; else baz”的行为不同

hud*_*dac 6 bash shell-script

我想

[ 1 -eq $1 ] && echo "yes" || echo "no"
Run Code Online (Sandbox Code Playgroud)

if [ 1 -eq $1 ]; then
    echo "yes"
else
    echo "no"
fi
Run Code Online (Sandbox Code Playgroud)

但是,当我运行这个脚本(nocmd是一个不存在的命令)

#!/bin/bash

[ 1 -eq $1 ] && nocmd "yes" || echo "no"
Run Code Online (Sandbox Code Playgroud)

我得到参数“1”的奇怪输出:

me@ubuntu:/tmp$ ./ddd.sh 0
no
me@ubuntu:/tmp$ ./ddd.sh 1
./sh.sh: line 3: nocmd: command not found
no
Run Code Online (Sandbox Code Playgroud)

看起来像这样:

if [ 1 -eq $1 ]; then
    nocmd "yes"
    if [ $? -ne 0 ]; then
        echo "no"
    fi
else
    echo "no"
fi
Run Code Online (Sandbox Code Playgroud)

好吗?我错过了什么吗?

Sté*_*las 20

除了整体退出状态外,它的作用类似于:

if
  ! { 
    [ 1 -eq $1 ] && nocmd "yes"
  }
then
  echo no
fi
Run Code Online (Sandbox Code Playgroud)

在:

A || B
Run Code Online (Sandbox Code Playgroud)

B执行 iffA失败。那是一个 OR 运算符。

在您的情况下A[ 1 -eq $1 ] && nocmd "yes"在哪里nocmd运行 iff[成功(AND 运算符),在这种情况下, 的退出状态A将是nocmd。换言之echo no将被执行,如果任一[nocmd "yes"失败(铭记nocmd如果只运行[成功)。

那些x && y || z是肮脏的黑客。出于这个原因,最好避免使用它们。使用if/ then/else如果你想有一个的if / then / else逻辑结构。使用x && y || z唯一的,如果你想z成为除非两个xy成功。

即使在:

cmd && echo OK || echo >&2 KO
Run Code Online (Sandbox Code Playgroud)

echo OK会的一些病理情况下可能会失败(如标准输出去一个文件在一个完整的文件系统),并echo >&2 KO最终可能也正在执行。

$ bash -c 'true && echo OK || echo KO >&2' > /dev/full
bash: line 0: echo: write error: No space left on device
KO
Run Code Online (Sandbox Code Playgroud)


Wei*_*hou 5

好吧,实际发生的事情是这样的(这就是工作方式&&||工作原理)

test 1 -eq $1
ret=$?
if [ $ret -eq 0 ]; then
    nocmd "yes"
    ret=$?
fi
if [ $ret -ne 0 ]; then
    echo "no"
fi
Run Code Online (Sandbox Code Playgroud)

在你的情况,如果$1不等于1或者是不是有效的数字,那么你有一个非零$?和第一if被跳过,而第二if打印“不”。如果$1equals 1,则nocmd "yes"执行,返回一个非零值$?,并且还回显“no”。