我编写了以下shell脚本。
if [ "$LOCALE" == "US" ]
then
#do something
elif [ "$LOCALE" == "DE" || "$LOCALE" == "FR" || "$LOCALE" == "IT" || "$LOCALE" == "UK" ]
then
#do something else.
fi
它给了我错误[: missing ]
。有人可以解释我这里有什么问题吗?
答案 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
语句可用的其他替代语法。