1. if
Shell 中 if 的语法是:
1 2 3 4 5 6 7
| if commands; then commands [elif commands; then commands]... [else commands] fi
|
如果 if 后面 commands 的返回值为 0 ,则执行 then 后面的 commands :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #!/bin/sh
foo () { return 0 }
bar () { return 1 }
if foo; then echo 'foo' fi
if bar; then echo 'bar' fi
|
输出:
也可以折成一行写,但 then 后面的 commands 后面也要用 ; 隔开:
1
| if bar; then echo 'bar'; fi
|
2. test
常见格式:
1 2
| test expression [ expression ]
|
test 会根据 expression 的 true/false 来返回 0/1 ,这样就可以结合 if 来使用了:
1 2 3 4 5 6 7 8 9 10 11
| foo=114514
if [ ${foo} = 114514 ]; then echo ok fi
if test ${foo} = 114514 ; then echo ok fi
|
2.1. 文件表达式
| 表达式 | 返回 0 时的情况 |
|---|
file1 -ef file2 | inode 相同的两个硬链接 |
file1 -nt file2 | file1 的修改时间比 file2 的更晚( file1 比 file2 新) |
file1 -ot file2 | file1 的修改时间比 file2 的更早( file1 比 file2 旧) |
-e file | file 存在 |
-f file | file 存在且是一个普通文件 |
-s file | file 存在且不是一个空文件 |
-d file | file 存在且是一个目录 |
-S file | file 存在且是一个 socket |
-h file/-L file | 存在且是一个符号链接 |
-p file | file 存在且是一个命名管道 |
-b file | file 存在且是一个块(设备)文件 |
-c file | file 存在且是一个字符(设备)文件 |
-g file | file 存在且设置了 setgid |
-u file | file 存在且设置了 setuid |
-k file | file 存在且设置了 sticky |
-r file | file 存在且用户有读取权限 |
-w file | file 存在且用户有写入权限 |
-x file | file 存在且用户有执行权限 |
-G file | file 存在且 GID 代表一个有效的组 |
-O file | file 存在且 UID 代表一个有效的用户 |
-t fd | fd 是一个被打开的 fd |
比如:
1 2 3
| if [ -x /bin/sh ]; then echo ok fi
|
但如果涉及到展开,最好用 "" 包住,因为:
1 2 3
| if [ -e ]; then echo ok fi
|
同样会输出 ok ,但:
1 2 3
| if [ -e "" ]; then echo ok fi
|
则不会输出 ok ,标准一点的写法是:
1 2 3
| if [ -e "${file}" ]; then echo ok fi
|
2.2. 字符串表达式
| 表达式 | 返回 0 时的情况 |
|---|
str/-n str | str 长度大于零 |
-z str | str 长度等于零 |
str1 = str2/str1 == str2 | 字符串相同 |
str1 != str2 | 字符串不同 |
str1 > str2 | ASCII (POSIX) 排序 str1 > str2 |
str1 < str2 | ASCII (POSIX) 排序 str1 < str2 |
> 和 < 需要用 ""/'' 包围或用 \ 转义,因为 Shell 会把 > 和 < 当作重定向符
1 2 3 4 5 6 7
| [ ] [ "" ] [ " " ] [ -z ] [ -z "" ] [ "foo" == "foo" ] [ "foo" '<' "bar" ]
|
2.3. 整数表达式
| 表达式 | 返回 0 时的情况 |
|---|
int1 -eq int2 | int1 == int2 |
int1 -ne int2 | int1 != int2 |
int1 -le int2 | int1 <= int2 |
int1 -lt int2 | int1 < int2 |
int1 -ge int2 | int1 >= int2 |
int1 -gt int2 | int1 > int2 |
1 2 3 4 5
| [ 114514 -eq 114514] [ "114514" -eq "114514" ] [ $(( 1 + 1 )) -eq 2 ] foo=1 [ $((${foo}+1)) -eq 2 ]
|
3. Bash 扩展
3.1. 更强大的 test
1 2 3
| [[ 114514 == 114* ]] [[ 114514 =~ ^[0-9]*$ ]] [[ $((1+1)) == 2 && $((2+2)) == 4 ]]
|
3.2. 更强大的整数运算
1 2 3 4 5
| foo=1 ((3)) ((0)) (( ${foo} == 1 )) (( foo == 1 ))
|
test 和 [ ] 本质上是一个程序(来自 coreutils ),所以所有表达式都被看作 Shell 参数,所以 <, >, (, ) 等字符需要进行转义,而 [[ ]] 和 (( )) 是 Shell 语法的一部分,里面的表达式会被视作 Shell 语法,所以不需要进行转义。
3.3. 逻辑运算符
| 逻辑运算符 | test | [[ ]] 和 (( )) |
|---|
| AND | -a | && |
| OR | -o | || |
| NOT | ! | ! |