有关bash中if的小结

最近在处理bash中的逻辑判断时, 碰到了一些问题, 这里稍微总结一下.

先看一下if的说明:

if list; then list; [ elif list; then list; ] … [ else list; ] fi

The if list is executed. If its exit status is zero, the then list is executed. Otherwise, each elif list is executed in turn, and if its exit status is zero, the corresponding then list is executed and the command completes. Otherwise, the else list is executed, if present. The exit status is the exit status of the last command executed, or zero if no condition tested true.

平常比较常见的用法是使用if cmd ;then do something; fi, cmd一般都是grep, kill之类的命令. 除此之外, 我们很多时候需要比较变量, 这时候我们会用到[[]], 也看一下:

[[ expression ]]

Return a status of 0 or 1 depending on the evaluation of the conditional expression expression. Expressions are composed of the primaries described below under CONDITIONAL EXPRESSIONS. Word splitting and pathname expansion are not performed on the words between the [[ and ]]; tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution, and quote removal are performed. Conditional operators such as -f must be unquoted to be recognized as primaries.

该命令会返回0或者1, 结合到if里面就是: 返回0则执行then, 否则执行else.

好, 接下来看4个小片段:

if.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/bin/bash

((v = $1 + 0))
echo "\$v is $v"

function tv()
{
    return $v
}

function myscript()
{
    perl -e 'exit 1'
}

## case 1
echo 'evaluate: [[ $v ]]'
if [[ $v ]]; then
    echo "true"
else
    echo "false"
fi

## case 2
echo 'evaluate: [[ $v -eq 1 ]]'
if [[ $v -eq 1 ]]; then
    echo "true"
else
    echo "false"
fi

## case 3 
echo 'evaluate: tv $v'
if tv $v; then
    echo "true"
else
    echo "false"
fi

## case 4
echo 'evaluate: script'
if myscript; then
    echo "true"
else
    echo "false"
fi

通过设置不同的$v的值, 会发现一些小问题. 先看case 1, 不论$v是什么数值, 总是true. 这是我最常犯的一个错误, 如果想要判断一个变量, 一定结合比较操作符. 正确的做法是像case 2一样.

case 3case 4都跟函数有关了, 就是简单的根据function的返回值来做不同的处理, 比较常用的用法.

最后再推荐一个stackoverflow上的一篇问答, 里面总结的很好.

题外话

在写脚本的时候发现自己理解的cd操作也是有问题的: 脚本中调用cd命令, 之后的脚本都是受影响的. 印象当中是不受影响的, 看来是和Makefile搞混了. 想要不受影响也很简单, 直接使用(cd xxx && do something)即可, 具体请看这里

Comments