Bash中的简单逻辑运算符

Ami*_*mit 237 bash logical-operators

我有几个变量,我想检查以下条件(用文字写出,然后我尝试bash脚本失败):

if varA EQUALS 1 AND ( varB EQUALS "t1" OR varB EQUALS "t2" ) then 

do something

done.
Run Code Online (Sandbox Code Playgroud)

在我失败的尝试中,我提出:

if (($varA == 1)) && ( (($varB == "t1")) || (($varC == "t2")) ); 
  then
    scale=0.05
  fi
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 636

你写的东西实际上几乎可以工作(如果所有变量都是数字,它会起作用),但它根本不是惯用的方式.

  • (…)括号表示子壳.它们里面的内容不像许多其他语言中那样.这是一个命令列表(就像外面的括号一样).这些命令在单独的子进程中执行,因此在括号内执行的任何重定向,赋值等都不会在括号外执行.
    • 使用前导美元符号,$(…)命令替换:括号内有一个命令,命令的输出用作命令行的一部分(在额外扩展之后,除非替换在双引号之间,但这是另一个故事) .
  • { … }大括号就像括号一样,它们对命令进行分组,但它们只会影响分析,而不会影响分组.该程序x=2; { x=4; }; echo $x打印4,而x=2; (x=4); echo $x打印2.(大括号需要在它们周围的空格和一个分号,然后关闭,而括号不.这只是一个语法怪癖.)
    • 带有一个领先的美元符号,${VAR}是一个参数扩展,扩展到变量的值,可能有额外的转换.
  • ((…))双括号围绕算术指令,即对整数的计算,其语法类似于其他编程语言.此语法主要用于赋值和条件.
    • 算术表达式中使用相同的语法$((…)),它扩展为表达式的整数值.
  • [[ … ]]双括号包围条件表达式.条件表达式主要基于运算符构建,例如-n $variable测试变量是否为空并-e $file测试文件是否存在.还有字符串相等运算符:"$string1" == "$string2"(提防右手边是一个模式,例如,[[ $foo == a* ]]如果测试$foo与启动a[[ $foo == "a*" ]]的测试,如果$foo是完全a*),和熟悉的!,&&||运营商的否定,合和脱节,以及对分组括号.请注意,每个操作符周围都需要一个空格(例如[[ "$x" == "$y" ]],不是[[ "$x"=="$y" ]]),;括号内部和外部都需要空格或字符(例如[[ -n $foo ]],不是[[-n $foo]]).
  • [ … ]单括号是条件表达式的另一种形式,具有更多的怪癖(但更旧,更便携).不要写任何东西; 当你找到包含它们的脚本时,开始担心它们.

这是用bash编写测试的惯用方法:

if [[ $varA == 1 && ($varB == "t1" || $varC == "t2") ]]; then
Run Code Online (Sandbox Code Playgroud)

如果你需要可移植到其他shell,这将是方式(注意额外的引用和每个单独测试周围的单独括号集):

if [ "$varA" = 1 ] && { [ "$varB" = "t1" ] || [ "$varC" = "t2" ]; }; then
Run Code Online (Sandbox Code Playgroud)

  • 伟大的帖子,括号摘要是理想的. (30认同)
  • 最好使用`==`来区分比较和赋值变量(也是`=`) (10认同)
  • 哦,我的意思是单(圆)括号,抱歉造成混乱。`[[ $varA = 1 && ($varB = "t1" || $varC = "t2") ]]` 中的那些不会启动子进程,尽管第一个要点明确指出:“[括号内] **不像许多其他语言那样是一个表达式**”——但它确实在这里!对于有经验的 bash 专家来说,这可能是显而易见的,但即使对我来说也不是,立即。之所以会出现混淆,是因为单括号 * 可以* 用于 `if` 语句中,而不能用于双括号内的表达式。 (3认同)
  • 您可以强调单括号在双括号内外具有完全不同的语义。(因为您一开始明确指出了子外壳语义,但后来只是顺便提到了分组语义作为条件表达式的一部分。当我查看您的惯用示例时,让我感到困惑一秒钟。) (2认同)
  • @protagonist`==`确实比“ =”更“惯用”。它们具有相同的含义,但是`==`是ksh的变体,也可以在bash和zsh中使用,而`=`是可移植的。使用`==`并没有任何优势,并且在普通sh中也不起作用。 (2认同)
  • @WillSheppard比较和赋值之间已经有许多其他区别:比较放在方括号内,赋值不在;比较运算符周围有空格,赋值没有;赋值在左边有一个变量名,比较很少有在左边看起来像变量名的东西,无论如何您都可以并且应该用引号引起来。如果愿意,可以在[[…]]`内编写`==`,但是`=`的优点是也可以在`[…]`中工作,所以我建议不要养成使用`==`的习惯。完全没有 (2认同)
  • @nakli_batman 不,`[[ ... ]]` 内的括号并不意味着子 shell。它们意味着操作员优先级。另请注意,即使您在子 shell 中运行整个条件(`if ( [[ $varA … ]] ); then …`),它仍然可以工作:子 shell 有自己的所有变量的副本,因此它可以使同样的计算,事实上,它是一个子 shell,只有当您更改内部变量时才重要,因为更改不会在父 shell 中看到。 (2认同)

mat*_*hew 33

很接近

if [[ $varA -eq 1 ]] && [[ $varB == 't1' || $varC == 't2' ]]; 
  then 
    scale=0.05
  fi
Run Code Online (Sandbox Code Playgroud)

应该管用.

打破它

[[ $varA -eq 1 ]] 
Run Code Online (Sandbox Code Playgroud)

是一个整数比较,其中as

$varB == 't1'
Run Code Online (Sandbox Code Playgroud)

是一个字符串比较.否则,我只是正确地对比分组.

双方括号分隔条件表达式.并且,我发现以下内容是关于这个主题的一个很好的解读:"(IBM)揭秘测试,[,[[,((和,if-then-else")


J.P*_*oni 6

一个非常可移植的版本(甚至可以使用旧版的bourne shell):

if [ "$varA" = 1 -a \( "$varB" = "t1" -o "$varB" = "t2" \) ]
then    do-something
fi
Run Code Online (Sandbox Code Playgroud)

这具有额外的质量,无论外壳的口味如何,最多只能运行一个子过程(即过程“ [”)。

如果变量包含数字值,则用“ -eq”替换“ =”

  • 3 -eq 03是正确的,但是
  • 3 = 03为假。(字符串比较)


小智 6

这是 if-then-else 语句的简短版本的代码:

( [ $a -eq 1 ] || [ $b -eq 2 ] ) && echo "ok" || echo "nok"
Run Code Online (Sandbox Code Playgroud)

请注意以下事项:

  1. ||&&if 条件内的操作数(即圆括号之间)是逻辑操作数(或/和)

  2. ||&&如果条件意味着 then/else和外部操作数

实际上,该声明说:

if (a=1 or b=2) then "ok" else "nok"