shell脚本中的字符串比较与OR条件

时间:2014-08-03 05:13:06

标签: shell

我编写了以下shell脚本。

if [ "$LOCALE" == "US" ]
then
   #do something

elif [ "$LOCALE" == "DE" || "$LOCALE" == "FR" || "$LOCALE" == "IT" || "$LOCALE" == "UK" ]
then
   #do something else.
fi

它给了我错误[: missing ]。有人可以解释我这里有什么问题吗?

2 个答案:

答案 0 :(得分:2)

[...]内,使用-a(和)和-o(或):

expr1 -a expr2

    True if both expr1 and expr2 are true.

expr1 -o expr2

    True if either expr1 or expr2 is true. 

[[...]]内,您可以使用&&(和)和||(或)。

答案 1 :(得分:1)

shell if运行一个命令(或者更专业地说,一个"管道",如本例所示):

if ls | grep xyzzy; then cmd1; cmd2; cmd3; fi

命令的退出状态确定then部分是否运行(或else部分是否运行)。如果管道"成功",即退出零 - 如果一个文件至少部分地命名为xyzzy,那么"然后"零件运行。

[命令......是一个命令! (它内置于所有现代shell变种中以提高速度,但它可以作为普通命令运行。)

sh-3.2$ [ a == b ]
sh-3.2$

[命令读取参数并要求它们以]结尾:

sh-3.2$ [
sh: [: missing `]'
sh-3.2$

这是您正在获取的错误,因为在sh语法中,prog1 || prog2表示首先运行prog1,然后只有在"失败" (退出非零),运行prog2。所以:

prog1 arg || grep xyzzy somefile
如果grep失败,

仅运行prog1。因此,反过来:

[ x || grep xyzzy somefile
如果grep失败,

运行[(由于语法错误,它会执行此操作)。

(旁白:我经常看到人们写的东西如下:

ls | grep xyzzy
if [ $? = 0 ]; then cmd1; cmd2; cmd3; fi

这是不必要的冗长,因为$?只是最后一个管道的退出状态,所以这与我的第一个例子相同。当然,有些人可能会说这个stackoverflow答案也不必要地啰嗦。 :-))

要让[程序测试多个条件,您可以使用其-a("和")和-o("或&#34 ;)运营商。然后,您只需运行一次[程序即可完成所有测试:

if [ "$LOCALE" == DE -o "$LOCALE" == FR ]; then ...; fi

或者,使用[程序的多次调用,但这在这里变得更加困难并开始需要括号或括号:

([ "$LOCALE" == DE ] || [ "$LOCALE" == FR ]) && (cmd1; cmd2; ...)

{ [ "$LOCALE" == DE ] || [ "$LOCALE" == FR ]; } && { cmd1; cmd2; ...; }

if { [ "$LOCALE" == DE ] || [ "$LOCALE" == FR ]; } then cmd1; cmd2; ... fi

(我不推荐这些替代方案:它们有效,但不必要地阅读。如果你必须使用一个,最后一个可能是最不可怕的。)

考虑用case替换所有这些:

case "$LOCALE" in
DE|FR|IT|UK) cmd1; cmd2; cmd3;;
*) other commands here;;
esac

case语句提供了glob-style匹配。例如,您可以将用户答案与混合大写和小写匹配:

need_answer=true
while $need_answer; do
    echo -n "should I do a thing? (yes/no, default = no) "
    read answer
    case "$answer" in
    [yY]|[yY][eE]|[yY][eE][sS])
        # handle "yes" case here
        need_answer=false;;
    [nN]|[nN][oO]|"")
        # handle "no" case here
        need_answer=false;;
        ;;
    *) echo "please answer yes or no";;
    esac
done

*通过全局匹配任何之前未匹配的输入,因为各种情况都是线性的,第一次匹配"胜出#34;。


有些shell(bash特别值得注意)有if语句可用的其他替代语法。