Bash中的三元运算符(?:)

En_*_*_t8 385 syntax bash conditional-operator

有没有办法做这样的事情

int a = (b == 5) ? c : d;
Run Code Online (Sandbox Code Playgroud)

用Bash?

gho*_*g74 434

三元运算符? :只是简短的形式if/else

case "$b" in
 5) a=$c ;;
 *) a=$d ;;
esac
Run Code Online (Sandbox Code Playgroud)

要么

 [[ $b = 5 ]] && a="$c" || a="$d"
Run Code Online (Sandbox Code Playgroud)

  • 注意`=`运算符测试字符串相等,而不是数字相等(即`[[05 = 5]]`为false).如果要进行数字比较,请改用"-eq". (91认同)
  • `cond && op1 || op2` construct有一个固有的错误:如果`op1`因任何原因而具有非零退出状态,结果将默默地变为`op2`.[`cond; op1; 别的op2; fi`](http://stackoverflow.com/a/25119904/648265)也是一行,没有那个缺陷. (59认同)
  • 这是利用短路行为获得三元运算符效果的天才方式:) :) :) (13认同)
  • 它更像是`if/then/else`的简短形式 (9认同)
  • 为什么[[和]]?它的工作原理如下:[$ b = 5] && a ="$ c"|| A = "$ d" (4认同)
  • 我感谢@ivan_pozdeev 的警告,但我反对称其为“错误”。我宁愿说“当使用`&&`时,您必须理解**AND**的含义”。意思是“两者都评估为真”。如果“opt1”可能为假,则当且**仅当**“opt2”不能为假时,您应该反转“cond”。如果这是**不**正确的,那么您的逻辑**不是** `&&` ... `||` 速记/逻辑的候选者,并且您必须使用 `if` ... `then` ... `else` 速记/逻辑。 (2认同)

Vla*_*mir 328

码:

a=$([ "$b" == 5 ] && echo "$c" || echo "$d")
Run Code Online (Sandbox Code Playgroud)

  • 这比其他人更好......关于第三运算符的观点是它是一个运算符,因此它的正确上下文在表达式中,因此它必须返回一个值. (47认同)
  • 与[其他答案]中的错误相同(http://stackoverflow.com/a/3953666/648265). (7认同)
  • 如果你肯定"&&"之后的命令不具有非零退出状态,那么这个*链*运算符的行为就像一个三元运算符.否则,`a && b || 如果`a`成功但是'b`失败,c`将"意外地"运行`c`. (6认同)
  • 这是最简洁的方式。请注意,如果带有 `echo "$c"` 的部分是别名、多行命令(如 `echo 1; echo 2`),则应将其括在括号中。 (2认同)
  • 这也将捕获已测试命令的任何输出(是的,在这种情况下,我们“知道”它不会产生任何输出)。 (2认同)
  • 有几个问题,启动一个子 shell,使用 `echo` 并且不引用结果。老实说,这种方法是将三元运算符的概念硬塞进一种没有三元运算符的语言中。如果我在野外遇到这个我会很困惑 (2认同)

nem*_*ixx 131

如果条件仅仅是检查是否设置了变量,那么甚至还有一个更短的形式:

a=${VAR:-20}
Run Code Online (Sandbox Code Playgroud)

将分配给if a的值,否则它将为其分配默认值- 这也可以是表达式的结果.VARVAR20

正如Alex在评论中指出的那样,这种方法在技术上被称为"参数扩展".

  • 不是OP想要的,但只是想说谢谢你今天教我一些新的东西,完全适合我的场景^_^ (9认同)
  • @KenWilliams实际上有一个类似的语法,它使用第二种类型的参数扩展,`:+`。您可以执行“${${VAR:+yes}:-no}”...如果“VAR”设置且非空,则这将扩展为“yes”,如果“VAR”未设置或为空,它将扩展为“yes”到“不”。 (8认同)
  • [懒人的链接](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html) - 除了替换 (`:-`) 之外,还有其他操作符 (5认同)
  • @JustinWrobel-不幸的是,没有像$ {VAR:-yes:-no}之类的语法。 (5认同)
  • `${${VAR+yes}:-no}` 适用于 `zsh (5.8)` (4认同)
  • 在传递带有连字符的字符串参数的情况下,我不得不使用引号:`a = $ {1: - 'my-hyphenated-text'}` (3认同)
  • @JoshuaSkrzypek,不,这行不通。`VAR=1;echo "${${VAR:+yes}:-no}"` → `-bash: ${${VAR:+yes}:-no}: 错误替换` 和 `VAR=; echo "${${VAR:+yes}:-no}"` → `-bash: ${${VAR:+yes}:-no}: 错误替换` (3认同)
  • @JulianMehnle 你完全正确,这是一种 zshism,而不是 bashism (3认同)

iva*_*eev 67

if [ "$b" -eq 5 ]; then a="$c"; else a="$d"; fi
Run Code Online (Sandbox Code Playgroud)

cond && op1 || op2其他答案中建议的表达式有一个固有的错误:如果op1具有非零退出状态,则op2默默地成为结果; 错误也不会在-e模式中被捕获.所以,这表达仅仅是安全的使用,如果op1不能失败(例如:,true如果一个内置的,或者不能够失败(如部门和操作系统调用)的任何操作变量赋值).

注意""引号.如果$b为空或具有空格,则第一对将防止语法错误.其他人会阻止将所有空格转换为单个空格.


小智 43

(( a = b==5 ? c : d )) # string + numeric
Run Code Online (Sandbox Code Playgroud)

  • 这对于**数字**比较和赋值是有好处的,但是如果你将它用于字符串比较和赋值,它会产生不可预测的结果....`(())`将任何/所有字符串视为`0` (27认同)
  • 也可以这样写:a = $((b == 5?c:d)) (3认同)

Sir*_*hos 31

[ $b == 5 ] && { a=$c; true; } || a=$d
Run Code Online (Sandbox Code Playgroud)

这将避免在||之后执行该部分 在&&和||之间的代码时偶然发生 失败.

  • 使用`:`bulit-in而不是`true`来保存`exec`一个外部程序. (2认同)
  • @TomHale No.` &&`和`||`的定义适用于它们之前的整个命令.因此,如果您之前有两个命令(无论它们如何组合),您不能将它仅应用于其中一个而不是另一个.你用文本变量_can_模拟`if` /`then` /`else`逻辑,但是如果有'if` /`then` /`else`正确的话,为什么还要烦恼呢? (2认同)

Jas*_*ich 13

这是另一个选项,您只需要指定一次分配的变量,无论您的分配是字符串还是数字都无关紧要:

VARIABLE=`[ test ] && echo VALUE_A || echo VALUE_B`
Run Code Online (Sandbox Code Playgroud)

只是一个想法.:)

  • 一个主要的缺点:它还会捕获`[ test ]` 的标准输出。因此,只有当您“知道”该命令不会向 stdout 输出任何内容时,才能安全地使用该构造。 (2认同)

emu*_*emu 11

命令支持大多数基本算一个需要的:

let a=b==5?c:d;
Run Code Online (Sandbox Code Playgroud)

当然,这仅适用于分配变量; 它无法执行其他命令.

  • 它完全等同于((...)),因此它仅对算术表达式有效 (23认同)

Bra*_*rks 7

以下似乎适用于我的用例:

例子

$ tern 1 YES NO                                                                             
YES

$ tern 0 YES NO                                                                             
NO

$ tern 52 YES NO                                                                            
YES

$ tern 52 YES NO 52                                                                         
NO
Run Code Online (Sandbox Code Playgroud)

并可以在如下的脚本中使用:

RESULT=$(tern 1 YES NO)
echo "The result is $RESULT"
Run Code Online (Sandbox Code Playgroud)

燕鸥

function show_help()
{
  echo ""
  echo "usage: BOOLEAN VALUE_IF_TRUE VALUE_IF_FALSE {FALSE_VALUE}"
  echo ""
  echo "e.g. "
  echo ""
  echo "tern 1 YES NO                            => YES"
  echo "tern 0 YES NO                            => NO"
  echo "tern "" YES NO                           => NO"
  echo "tern "ANY STRING THAT ISNT 1" YES NO     => NO"
  echo "ME=$(tern 0 YES NO)                      => ME contains NO"
  echo ""

  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$3" ]
then
  show_help
fi

# Set a default value for what is "false" -> 0
FALSE_VALUE=${4:-0}

function main
{
  if [ "$1" == "$FALSE_VALUE" ]; then
    echo $3
    exit;
  fi;

  echo $2
}

main "$1" "$2" "$3"
Run Code Online (Sandbox Code Playgroud)

  • 很解释.非常完整.非常冗长.我喜欢的三件事.;-) (5认同)
  • 嘿@太极者无极而生 - 这是bash脚本的名称 - 将上面的"tern"部分保存到名为"tern"的文件中,然后在同一个文件夹中运行`chmod 700 tern`.现在你的终端上有一个`tern`命令 (3认同)
  • 是Bash的“ tern”部分吗?Mac似乎没有它 (2认同)

Suj*_*U N 6

对于三元运算符,我们可以在Shell脚本中使用以下三种方式:

    [ $numVar == numVal ] && resVar="Yop" || resVar="Nop"

Or

    resVar=$([ $numVar == numVal ] && echo "Yop" || echo "Nop")

Or

    (( numVar == numVal ? (resVar=1) : (resVar=0) ))
Run Code Online (Sandbox Code Playgroud)

  • 恕我直言,这实际上是(这三个例子中的第一个和第二个)最合适的答案。 (2认同)

Ste*_*erl 6

这是一个通用的解决方案,即

  • 也适用于字符串测试
  • 感觉更像是一种表达
  • 当条件失败时避免任何微妙的副作用

用数值比较测试

a=$(if [ "$b" -eq 5 ]; then echo "$c"; else echo "$d"; fi)
Run Code Online (Sandbox Code Playgroud)

使用字符串比较进行测试

a=$(if [ "$b" = "5" ]; then echo "$c"; else echo "$d"; fi)
Run Code Online (Sandbox Code Playgroud)


wib*_*ble 5

(ping -c1 localhost&>/dev/null) && { echo "true"; } || {  echo "false"; }
Run Code Online (Sandbox Code Playgroud)


小智 5

bash中的三元条件也有一个非常相似的语法:

a=$(( b == 5 ? 123 : 321  ))
Run Code Online (Sandbox Code Playgroud)

不幸的是,据我所知,它仅适用于数字。

  • 仅对“算术扩展”有效,是的,即不适用于字符串或任何“测试”结果。 (3认同)