如何在if语句条件表达式里面调用外部命令(函数,或者外部脚本),然后根据外部命令的执行结果确定走什么分支。
基本语法:
if command; then
do-actions;
fi
含义是命令command如果执行成功,也就是返回值为0,那么执行do-actions,否则就不执行。
反过来场景,如果命令command执行不成功,也就是返回值不为0,那么执行do-actions的格式是:
if ! command; then
do-actions;
fi
给一个例子:
#!/bin/bash
function foo() {
if [ "${1}" == "YES" ]; then
echo "It's YES"
return 0
else
echo "It's not YES"
return 1
fi
}
if foo "YES"; then
echo "Match: YES"
fi
if ! foo "Not YES"; then
echo "Match: Not YES"
fi
运行结果如下:
It's YES
Match: YES
It's not YES
Match: Not YES
进一步,能不能具体到不同的返回值呢
前面例子中我们只是判断命令是否执行成功,也就是返回时是否为0,那么能不能区分具体的返回值呢,例如当返回值为1时,才执行do-actions,其他返回值2、3、...忽略呢;像:
if command == 1; then
do-actions
fi
我查了一些资料,遗憾的是没有找到有这样的办法,基本上只能先调用命令,然后判断返回值,像:
command
if [ $? - eq 1 ]; then
do-actions
fi
或者,
ret=command
if [ ${ret} - eq 1 ]; then
do-actions1
elif [ ${ret} - eq 2 ]; then
do-actions
elif [ ${ret} - eq 3 ]; then
do-actions3
elif ...
...
fi
又,能不能使用输出而不是返回值判断呢
当然是可以的,正常使用$(command)得到输出,然后比较就行了。
#!/bin/bash
function foo() {
if [ "${1}" == "YES" ]; then
echo "It's YES"
return 0
else
echo "It's not YES"
return 1
fi
}
if [ "$(foo 'YES')" == "It's YES" ]; then
echo "Match: YES"
fi
if [ "$(foo 'NO')" == "It's not YES" ]; then
echo "Match: NO"
fi
运行结果:
Match: YES
Match: NO
需要注意的是,判断命令输出的例子中,我们把命令的返回值丢弃了,也就是并没有判断命令是否执行成功,只判断了输出是什么。
如果要严格判断,
OUT1="$(foo 'YES')"
if [ $? -eq 0 -a "${OUT1}" == "It's YES" ]; then
echo "Match: YES"
fi
OUT2="$(foo 'NO')"
if [ $? -eq 0 -a "${OUT2}" == "It's not YES" ]; then
echo "Match: NO"
fi
这样运行结果:
Match: YES
此时,第二部分判断就不成立,以为$?不为0了。
又,判断多个命令的执行
可以使用&&和||来组合多个命令的执行。
#!/bin/bash
function foo00() { echo foo00; return 0; }
function foo01() { echo foo01; return 0; }
function foo10() { echo foo10; return 1; }
function foo11() { echo foo11; return 1; }
if foo00 "ppp" && foo01 "PPP"; then
echo "case 1: pass"
else
echo "case 1: fail"
fi
if foo00 "ppp" && foo10 "PPP"; then
echo "case 2: pass"
else
echo "case 2: fail"
fi
if foo10 "ppp" && foo01 "PPP"; then
echo "case 3: pass"
else
echo "case 3: fail"
fi
if foo10 "ppp" && foo11 "PPP"; then
echo "case 4: pass"
else
echo "case 4: fail"
fi
if foo00 "ppp" || foo01 "PPP"; then
echo "case 1: pass"
else
echo "case 1: fail"
fi
if foo00 "ppp" || foo10 "PPP"; then
echo "case 2: pass"
else
echo "case 2: fail"
fi
if foo10 "ppp" || foo01 "PPP"; then
echo "case 3: pass"
else
echo "case 3: fail"
fi
if foo10 "ppp" || foo11 "PPP"; then
echo "case 4: pass"
else
echo "case 4: fail"
fi
执行结果:
foo00
foo01
case 1: pass
foo00
foo10
case 2: fail
foo10
case 3: fail
foo10
case 4: fail
foo00
case 1: pass
foo00
case 2: pass
foo10
foo01
case 3: pass
foo10
foo11
case 4: fail
又,如何用括号分组命令
例如条件A满足,并且条件B或者条件C满足,类似:
A && (B || )
#!/bin/bash
function foo00() { echo foo00; return 0; }
function foo01() { echo foo01; return 0; }
function foo10() { echo foo10; return 1; }
function foo11() { echo foo11; return 1; }
if foo00 && ( foo01 "BB" || foo11 "CC" ); then
echo "case 1: pass"
else
echo "case 1: fail"
fi
if foo00 && ( foo10 "BB" || foo11 "CC" ); then
echo "case 1: pass"
else
echo "case 1: fail"
fi
运行结果:
foo00
foo01
case 1: pass
foo00
foo10
foo11
case 1: fail
又,普通条件和函数混合使用
$ cat t.sh
#!/bin/bash
function foo0() {
return 0
}
function foo1() {
return 1
}
if [ "a" == "a" ] && foo0; then echo "YES1"; fi
if [ "a" == "a" ] && foo1; then echo "YES2"; fi
if [ "a" == "a" ] || foo0; then echo "YES3"; fi
if [ "a" == "a" ] || foo1; then echo "YES4"; fi
if [ "a" == "b" ] && foo0; then echo "YES5"; fi
if [ "a" == "b" ] && foo1; then echo "YES6"; fi
if [ "a" == "b" ] || foo0; then echo "YES7"; fi
if [ "a" == "b" ] || foo1; then echo "YES8"; fi
$ ./t.sh
YES1
YES3
YES4
YES7
这里要注意写法,用&&和||,必须用在[]括号外面,不能放里面:
if [ "a" == "a" && foo ];
if [ "a" == "a" -a foo ];
这两种写法都是错误的。
原因是因为[]和test是等效的,一个[]表达式和一个test是一样的,所有上述写法相当于把foo函数调用写入test语法里面,这是不通的。
- [ expression ] == test expressio
- expression支持与(-a),或(-o),和非(!)
比如 [ "a" == "a" -a foo ]等价于 test "a" == "a" -a foo,这个表达式总是返回成功,不管函数foo的返回0还是1。其实在这个情况下,foo并不被认为是一个函数,而是被认为是一个字符串,和"foo"等价:
[ "a" == "a" -a "foo" ]
我们看test的帮助,有这个说明:
$ man test
-n STRING
the length of STRING is nonzero
STRING equivalent to -n STRING
也就是说此时的foo,等价于"foo",等价于 -n "foo",长度是3肯定不等于0,所以表达式总是返回true,而和函数foo没有任何关系了。
小结
- if语句调用外部命令时,不要方括号'[]',而直接写命令(包括带参数)即可。
- 只能判断命令执行是否成功,返回值0还是非0,不能区分具体的返回值。
- 支持多条命令的与或操作, '&& 和 ||'
- 支持圆括号'()'对命令进行分组。
网友评论