目录
条件测试语句用来测试指定的条件表达式是真还是假。当条件为真是返回0,反之返回非0值。这与一般的编程语言相反,请大家注意。
条件测试的语法有两种:分别是 test命令 和 [命令。
- test expression
- [ expression ]
其中参数expression是条件表达式,可由字符串、数字、文件名,以及各种运算符组成。
[命令与test命令一样,也是对后面的条件表达式进行测试,但是为了增加程序可读性,Shell要求在条件表达式的右边添加一个右方括号]来与前面[命令配对,
注意expression和 [,]之间都有一个空格!因为"左方括号"也是一条shell命令,命令和参数之间必须有空格。
对于字符串的判断主要是判断是否为空,是否相等。用户可以通过下表列出的5种运算符进行操作
| 运算符 | 说明 |
|---|---|
| string | 判断指定的字符串是否为空,不为空返回0 |
| string1 = string2 | 判断两个字符串是否相等,相等返回0 |
| string1 != string2 | 判断两个字符串是否不相等,不相等返回0 |
| -n string | 判断string是否为非空串,非空返回0 |
| -z string | 判断string是否为空串,空串返回0 |
对于上表的第一个运算符,只能使用test命令来测试,其余4种,两种测试方式都支持。
在进行字符串比较时,用引号将字符串界定起来是一个非常好的习惯。
- #!/bin/bash
- a="abc"
- b=""
- test $a
- #非空返回0
- echo $?
-
- test $b
- #空返回非0
- echo $?
-
- test -n $a
- #非空返回0
- echo $?
-
- test -z $a
- #非空返回非0
- echo $?
-
- [ -n $a ]
- #非空返回0
- echo $?
-
- [ -z $a ]
- #非空返回非0
- echo $?
-
- test "$a" = "$b"
- #不相等返回非0
- echo $?
-
- [ "$a" != "$b" ]
- #不相等返回0
- echo $?
结果如下:
eden_ubuntu@edenubuntu:~/Documents/Shell$ ./4-1.sh
0
1
0
1
0
1
1
0
注意:字符串比较是区分大小写的。
这里的 = 和 != 都是运算符,在使用的时候,前后都需要加空格,切记。
整数测试的两种语法和字符串类似:
- test number1 op number2
- [ number1 op number2]
number1和number2表示参与比较的整数,可以是常量和变量,op表示运算符。下表列出常用的整数运算符:
| 运算符 | 说明 |
|---|---|
| num1 -eq num2 | 判断两个数是否相等,相等返回0 |
| num1 -ne num2 | 判断两个数是否不相等,不相等返回0 |
| num1 -gt num2 | 判断num1是否大于num2,大于返回0 |
| num1 -lt num2 | 判断num1是否小于num2,小于返回0 |
| num1 -ge num2 | 判断num1是否大于等于num2,大于等于返回0 |
| num1 -le num2 | 判断num1是否小于等于num2,小于等于返回0 |
实例:
- #!/bin/bash
- a=12
- b=14
-
- [ "$a" -eq "$b"]
- #不相等返回非0
- echo $?
-
- test "$a" -ne "$b"
- #不相等返回0
- echo $?
-
- [ "$a" -eq 12 ]
- #相等返回0
- echo $?
-
- [ "$a" -gt "$b" ]
- #不大于返回非0
- echo $?
-
- [ "$a" -lt "$b" ]
- #小于返回0
- echo $?
-
- [ "$a" -ge "12" ]
- #大于等于返回0
- echo $?
结果:
eden_ubuntu@edenubuntu:~/Documents/Shell$ ./4-2.sh
1
0
0
1
0
0
如果[]之间没有空格,提供将会报错,比如我]前不加空格,系统提示缺失 ] 符号:
./4-2.sh: line 5: [: missing `]'
Shell提供了许多与文件有关的操作符来对文件进行检测。如下表:
| 操作符 | 说明 |
|---|---|
| -a file | 判断文件是否存在,存在返回0 |
| -b file | 判断文件是否存在并且文件类型为块文件,是返回0 |
| -c file | 判断文件是否存在并且文件类型为字符文件,是返回0 |
| -d file | 判断文件是否存在并且文件类型为目录,是返回0 |
| -e file | 效果与-a相同 |
| -f file | 判断文件是否存在并且为常规文件,是返回0 |
| -s file | 判断file是否是一个非空文件,是返回0 |
| -w file | 判断文件是否存在并且文件可写,是返回0 |
| -r file | 判断文件是否存在并且文件可读,是返回0 |
| -x file | 判断文件是否存在并且文件可执行,是返回0 |
| -L file | 判断文件是否存在并且文件是一个符号链接,是返回0 |
| -u file | 判断文件是否存在并且是否设置了suid位,是返回0 |
主要检测3方面:文件是否存在;文件的类型;文件的访问权限。
首先在一个目录下创建目录和一些文件,情况如下所示:
eden_ubuntu@edenubuntu:~/Documents/Shell/4-3$ ll
total 16
drwxrwxr-x 3 eden_ubuntu eden_ubuntu 4096 Jul 26 00:26 ./
drwxrwxr-x 3 eden_ubuntu eden_ubuntu 4096 Jul 26 00:18 ../
-rw-rw-r-- 1 eden_ubuntu eden_ubuntu 0 Jul 26 00:26 file1
-rw-rw-r-- 1 eden_ubuntu eden_ubuntu 3 Jul 26 00:27 file2
lrwxrwxrwx 1 eden_ubuntu eden_ubuntu 9 Jul 26 00:19 shortcut.sh -> ../4-2.sh*
drwxrwxr-x 2 eden_ubuntu eden_ubuntu 4096 Jul 26 00:18 tmpDir/
执行测试实例:
- #!/bin/bash
- test -d tmpDir
- echo $?
-
- test -f file1
- #file1存在且为普通文件
- echo $?
-
- test -s file1
- #file1大小为0,返回非0
- echo $?
-
- test -s file2
- #file1存在且file1大小大于0,返回0
- echo $?
-
- test -L shortcut.sh
- #shortcut.sh存在且为符号链接,返回0
- echo $?
-
- test -b file1
- #file1不是块文件,返回非0
- echo $?
-
- test -b /dev/sda
- #/dev/sda存在且/dev/sda是块文件,返回0
- echo $?
-
- test -c /dev/tty
- #控制终端/dev/tty存在且/dev/tty是字符文件,返回0
- echo $?
结果:
eden_ubuntu@edenubuntu:~/Documents/Shell/4-3$ ./4-3.sh
0
0
1
0
0
1
0
0
在Shell编程中,经常会遇到判断多个条件的情况,将多个条件组合成一个条件进行判断,用到 非、或和与的逻辑。看下表
| 操作符 | 说明 |
|---|---|
| ! expression | 逻辑非 |
| expression1 -a expression2 | 逻辑与 |
| expression1 -o expression2 | 逻辑或 |
举个简单例子:
- #!/bin/bash
- a=35
- test "$a" -gt 30 -a "$a" -lt 40
- echo $?
结果如下:
eden_ubuntu@edenubuntu:~/Documents/Shell$ ./4-4.sh
0
条件判断句使得程序可以根据不同的条件来执行不同的程序分支,主要就是if语句,if else语句,if elif语句,下面列出各种语句的例子。
语法为:
- if expression
- then
- statement1
- statement2
- ...
- fi
-
- 为了使得代码更加紧凑,我们可以让if子句和then子句放在一行,这时候需要在expression表达式后加一个;号
- if expression; then
- statement1 statement2 ...
- fi
- 或者
- if expression; then statement1 statement2 ...; fi
示例如下:
- #!/bin/bash
- if [ -f ./4-5.sh ]
- then
- echo "./4-5.sh is a file"
- fi
-
- if test -f ./4-5.sh
- then echo "./4-5.sh is a file"
- fi
-
- if [ -f ./4-5.sh ]; then echo "./4-5.sh is a file"; fi
-
- if :; then echo "always ture"; fi
可以看到if后面可以用 test命令,也可以用[命令
结果为:
eden_ubuntu@edenubuntu:~/Documents/Shell$ ./4-5.sh
./4-5.sh is a file
./4-5.sh is a file
./4-5.sh is a file
always ture
在Shell中还有一个特殊的命令,称为空命令,其表示方法是一个冒号:,改命令不做任何事情,但是它的退出状态永远是0,就是永远为真,在上述例子中我们有展示。
还有的人喜欢用&&操作符代替if语句,如下面的例子:
- #!/bin/bash
- test -f './4-5.sh' && echo './4-5.sh is a file'
- ! test -f './4-5-.sh' && echo './4-5.sh is not a file'; exit 1
结果:
eden_ubuntu@edenubuntu:~/Documents/Shell$ ./4-6.sh
./4-5.sh is a file
./4-5.sh is not a file
语法为:
- if expression
- then
- statement1
- statement2
- ...
- else
- statement3
- statement4
- ...
- fi
语法为:
- if expression1
- then
- statement1
- statement2
- ...
- elif expression2
- then
- statement3
- statement4
- ...
- ...
- else
- statementn
- fi
上面两个语句就不多讲了,和其他语言类似的,知道if的用法,这两个是类似的。
类似于C++,java的是switch语句,语法如下:
- case variable in
- value1)
- statement1
- ...
- statementn
- ;;
- value1)
- statement1
- ...
- statementn
- ;;
- value1)
- statement1
- ...
- statementn
- ;;
- *)
- statement1
- ...
- statementn
- ;;
- esac
其中*)就是default选项,当其他分支都没有进去的时候会进入这个分支。
case语句结构以esac结尾,和if语句以fi结构一样,都是以命令名倒序作为命令结尾。
除了前面列出的一些运算符外,还有一些与数值有关的运算符,比如算术运算符、位运算符、自增/减运算符等。首先我们看看算术运算符,和其他编程语言差不多
| 运算符 | 说明 |
|---|---|
| + | 求两数之和 |
| - | 求2数之差 |
| * | 求2数之乘积 |
| / | 求2数之商 |
| % | 求余/取模 |
| ** | 幂运算,这个特殊一点,举例:3**4就是3的4次幂 |
下面看下复合算术运算符,这个和C语言中的是一样的,不做过多解释
| 运算符 | 说明 |
|---|---|
| += | 求和后,再将和赋值给左边的变量 |
| -= | 求差值后,再将和赋值给左边的变量 |
| *= | 求乘积后,再将和赋值给左边的变量 |
| /= | 求商后,再将和赋值给左边的变量 |
| %/ | 取余后,再将和赋值给左边的变量 |
Shell编程也支持位运算符,用法和C语言一样,但是可能用的比较少,下面我们看表
| 运算符 | |
|---|---|
| << | 左移 |
| >> | 右移 |
| & | 按位与 |
| | | 按位或 |
| ~ | 按位非 |
| ^ | 按位异或 |
位运算符也有复合运算符
| 运算符 | |
|---|---|
| >>= | 左移后将值赋值给左边的变量 |
| <<= | 右移后将值赋值给左边的变量 |
| &= | 按位与后将值赋值给左边的变量 |
| |= | 按位或后将值赋值给左边的变量 |
| ^= | 按位异或后将值赋值给左边的变量 |
用法与C语言一样
| 运算符 | 说明 |
|---|---|
| ++variable | 先将variable的值加1,然后再赋值给variable |
| --variable | 先将variable的值减1,然后再赋值给variable |
| variable++ | 先使用variable的值,然后再将variable的值加1 |
| variable-- | 先使用variable的值,然后再将variable的值减1 |
在Shell中有4种方式执行算术运算,分别如下:
使用这种形式进行算术运算写法比较自由,无需对运算符和括号做转义处理,可以采用松散或者紧凑的格式来书写表达式。举例:
- #!/bin/bash
- #采用紧凑格式
- result=$((3+7))
- echo "$result"
-
- #采用松散格式
- result=$(( 3 - 7 ))
- echo "$result"
-
- result=$((3*7))
- echo "$result"
-
- result=$((8/3))
- echo "$result"
-
- result=$((8%3))
- echo "$result"
-
- result=$((2**3))
- echo "$result"
-
- #复合运算
- result=$(((3+7)*2))
- echo "$result"
结果:
eden_ubuntu@edenubuntu:~/Documents/Shell$ ./4-7.sh
10
-4
21
2
28
20
这个使用方法与$((expression))基本相同,举例:
- #!/bin/bash
- #采用紧凑格式
- result=$[3+7]
- echo "$result"
-
- #采用松散格式
- result=$[ 3 - 7 ]
- echo "$result"
-
- result=$[3*7]
- echo "$result"
-
- result=$[8/3]
- echo "$result"
-
- result=$[8%3]
- echo "$result"
-
- result=$[2**3]
- echo "$result"
-
- #复合运算
- result=$[(3+7)*2]
- echo "$result"
结果与上面一致。
eden_ubuntu@edenubuntu:~/Documents/Shell$ ./4-8.sh
10
-4
21
2
2
20
[]与(()) 的差别在于[]里面不能进行赋值操作,而(())里面支持赋值操作,这个差别可以在后面的 数值常量的进制的例子中看到,大家有兴趣也可以试试。
expr是一个Shell命令,使用语法:
expr expression
它使用起来有比较多的讲究,不大好用。在使用运算符时,需要对运算符进行转义,如果有括号,也需要对括号进行转义。不能使用紧凑格式,要使用松散格式,举例:
- #!/bin/bash
- result=`expr 2 + 100`
- echo "$result"
-
- result=`expr 2 - 100`
- echo "$result"
-
- result=`expr 2 \* 100`
- echo "$result"
-
- result=`expr 100 / 2`
- echo "$result"
-
- result=`expr 100 % 3`
- echo "$result"
-
- result=`expr \( 1 + 3 \) \* 5`
- echo "$result"
-
- #错误语法
- result=`expr 2+5`
- echo "$result"
-
- #错误语法
- result=`expr 2+5*10`
- echo "$result"
-
- #错误语法
- result=`expr 2*(2+5)`
- echo "$result"
结果:
eden_ubuntu@edenubuntu:~/Documents/Shell$ ./4-9.sh
102
-98
200
50
1
20
2+5
2+5*10
./4-9.sh: command substitution: line 29: syntax error near unexpected token `('
./4-9.sh: command substitution: line 29: `expr 2*(2+5)'
可以看到前面6项都是正常的,到第7项和第8项结果未到预期,不是整数值而是一个表达式 ,第9项报错。所以使用时要注意避免上述的错误。
使用let命令可以执行一个或者多个算术表达式,其中的变量名无需使用$符号。如果表达式中含有空格或者其他特殊字符,需要引用起来。举例:
- #!/bin/bash
- n=10
- let n=n+1
- echo "$n"
-
- let n-=1
- echo "$n"
-
- let n=n**2
- echo "$n"
-
- let n--
- echo "$n"
-
- let n**3
- echo "$n"
let的表达式最后要有赋值才有效果。 let n**3是不会修改n的值的。
结果如下:
eden_ubuntu@edenubuntu:~/Documents/Shell$ ./4-10.sh
11
10
100
99
99
默认情况下,Shell总是以十进制来表示数字。但是用户也可以在Shell中使用其他进制来表示数字,比如二进制,八进制,十六进制。在Shell中,用户可以使用两种语法来表示不同的进制
1.增加前缀:0开头的数字表示0进制,0x开头的数字表示十六进制
2.使用#号:2#1001表示二进制,8#20表示八进制
实例如下:
- #!/bin/bash
- a=$((2#1000))
- ((b=8#20))
- ((c=16#10))
-
- d=$[0x10]
- e=$[020]
- f=20
- ((g=0x10))
-
- ((h=(1+3)*5))
- echo "$a $b $c $d $e $f $g $h"
结果如下:
eden_ubuntu@edenubuntu:~/Documents/Shell$ ./4-11.sh
8 16 16 16 16 20 16 20
本篇主要探讨了条件测试,判断语句,运算符以及运算符的使用方法等