如何在shell if语句中表示多个条件?

use*_*955 288 unix bash shell

我想代表这样的多个条件:

if [ ( $g -eq 1 -a "$c" = "123" ) -o ( $g -eq 2 -a "$c" = "456" ) ]   
then  
    echo abc;  
else  
    echo efg;   
fi  
Run Code Online (Sandbox Code Playgroud)

但是当我执行脚本时,它会显示出来

syntax error at line 15: `[' unexpected, 
Run Code Online (Sandbox Code Playgroud)

第15行显示是否....

这种情况怎么了?我猜这有点不对劲().

Jon*_*ler 361

经典技术(转义元字符):

if [ \( "$g" -eq 1 -a "$c" = "123" \) -o \( "$g" -eq 2 -a "$c" = "456" \) ]
then echo abc
else echo efg
fi
Run Code Online (Sandbox Code Playgroud)

我把参考文献$g用双引号括起来; 总的来说,这是一种很好的做法.严格来说,并不需要括号,因为的优先级-a,并-o使其正确的,即使没有它们.

需要注意的是,-a-o运营商的POSIX规范的一部分test,又名[,主要是为了向后兼容(因为他们的一部分,test在第7版UNIX等),但它们被明确标记为POSIX"过时".Bash(参见条件表达式)似乎抢占了经典和POSIX的含义,-a并且-o使用自己的带有参数的替代运算符.


需要注意的是,您可以使用更现代的[[运算符,但请注意Bash和Korn Shell中的版本(例如)不必相同.

for g in 1 2 3
do
    for c in 123 456 789
    do
        if [[ ( "$g" -eq 1 && "$c" = "123" ) || ( "$g" -eq 2 && "$c" = "456" ) ]]
        then echo "g = $g; c = $c; true"
        else echo "g = $g; c = $c; false"
        fi
    done
done
Run Code Online (Sandbox Code Playgroud)

示例运行,在Mac OS X上使用Bash 3.2.57:

g = 1; c = 123; true
g = 1; c = 456; false
g = 1; c = 789; false
g = 2; c = 123; false
g = 2; c = 456; true
g = 2; c = 789; false
g = 3; c = 123; false
g = 3; c = 456; false
g = 3; c = 789; false
Run Code Online (Sandbox Code Playgroud)

您不需要像处理那样引用变量[[,[因为它不是一个单独的命令[.


这不是一个经典的问题吗?

我会这么想的.但是,还有另一种选择,即:

if [ "$g" -eq 1 -a "$c" = "123" ] || [ "$g" -eq 2 -a "$c" = "456" ]
then echo abc
else echo efg
fi
Run Code Online (Sandbox Code Playgroud)

实际上,如果你阅读了autoconf工具或相关软件包的"便携式外壳"指南,这种符号 - 使用' ||'和' &&' - 是他们推荐的.我想你甚至可以做到:

if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi
Run Code Online (Sandbox Code Playgroud)

如果行动像回声一样微不足道,那也不错.当要重复的动作块是多行时,重复过于痛苦,并且最好使用早期版本之一 - 或者您需要将动作包装到在不同then块中调用的函数中.

  • 很高兴知道逃脱的括号工作; 旁白:在这种特殊情况下,甚至不需要括号,因为`-a`实际上比`-o'具有更高的优先级(不像shell中的`&&`和`||` - 但是,_inside_`bash ``[[...]]`_ conditionals_,`&&`_also_的优先级高于`||`.如果你想避免`-a`和`-o`以获得最大的健壮性和可移植性 - [POSIX手册页本身](http://man.cx/test)建议 - 你也可以使用_subshel​​ls_进行分组: if([$ g -eq 1] && ["$ c"="123"])|| ([$ g -eq 2] && ["$ c"="456"])` (9认同)

Pau*_*ce. 176

在Bash:

if [[ ( $g == 1 && $c == 123 ) || ( $g == 2 && $c == 456 ) ]]
Run Code Online (Sandbox Code Playgroud)

  • 绝对是'bash`中最好的方法.暂且不说:在这种特殊情况下,甚至不需要括号,因为_inside_` [[...]]`_conditionals_` &&`实际上具有比`||'更高的优先级 - 与_outside_这样的条件不同. (8认同)
  • 两个方括号的用途是什么? (2认同)
  • @peter:请参阅我的答案[这里](http://stackoverflow.com/a/2188369/26428),[Bash手册中的条件构造](https://www.gnu.org/software/bash/manual /html_node/Conditional-Constructs.html#Conditional-Constructs)和[BashFAQ/31](http://mywiki.wooledge.org/BashFAQ/031). (2认同)

sun*_*tha 31

使用/bin/bash以下将工作:

if [ "$option" = "Y" ] || [ "$option" = "y" ]; then
    echo "Entered $option"
fi
Run Code Online (Sandbox Code Playgroud)


Ash*_*ana 9

在 Bash 中,您可以使用以下技术进行字符串比较

if [ $var OP "val" ]; then
    echo "statements"
fi
Run Code Online (Sandbox Code Playgroud)

例子:

var="something"
if [ $var != "otherthing" ] && [ $var != "everything" ] && [ $var != "allthings" ]; then
    echo "this will be printed"
else
    echo "this will not be printed"
fi
Run Code Online (Sandbox Code Playgroud)


gho*_*g74 7

$ g=3
$ c=133
$ ([ "$g$c" = "1123" ] || [ "$g$c" = "2456" ]) && echo "abc" || echo "efg"
efg
$ g=1
$ c=123
$ ([ "$g$c" = "1123" ] || [ "$g$c" = "2456" ]) && echo "abc" || echo "efg"
abc
Run Code Online (Sandbox Code Playgroud)

  • 那是没用的子shell。可以使用`{;}`。 (2认同)

ork*_*den 7

如果字符串变量中有空格并检查是否存在,请小心.一定要正确引用它们.

if [ ! "${somepath}" ] || [ ! "${otherstring}" ] || [ ! "${barstring}" ] ; then
Run Code Online (Sandbox Code Playgroud)

  • 当我们在美元符号后面使用大括号时!! (2认同)