分支循环是编程语言重要结构,它使得计算机源源不断地给搬砖。Shell 中也有对应语法支持。
在分支循环结构中,判断条件十分重要,在 Shell 中可以用 test 命令来判断条件。
1. test 命令
test 在 Shell 用于测试判断,如其名字所示,它可以进行一些测试,如:
- 两个字符串是否相等
- 给定路径是否存在
- 路径是否有各种权限
- ……
语法如下:
test condition
test $a -eq 5
判断为逻辑真,返回 0,判断值为假返回值 1。返回值不能用 e=$(test $a -eq 5) 来获取,这样运算后 e 是空。而要用 $? 的方式来获取。$? 用于获取上一条命令的返回值。
test 1 -eq 2
echo $? # output 1, which means false
test 1 -eq 1
echo $? # output 0, which means true
test 的返回值可以作为条件判断(如 if else)的条件:
if test "${a}" -eq 5; then echo $a; fi
test 命令也可以用单中括号([])来代替,只是使用单中括号时候,需要注意在中括号和条件之间必须有空格( )。
if [ -e ex ]; then echo "exist ex"; else echo "not exist ex"; fi
if test -e ex; then echo "exist ex"; else echo "not exist ex"; fi
1.1 路径判断
Linux 中文件不一定有扩展名,文件和文件夹的名字没有区别。
| 函数 | 意义 |
|---|---|
-e | 路径存在(文件或文件夹)则返回 true,否则 false,e 是 exist 的意思 |
-d | 路径存在且是文件夹则返回 true,否则 false,d 是 directory 的意思 |
-f | 路径存在且是文件则返回 true,否则 false,f 是 file 的意思 |
-n | 路径存在且大小不为零则返回 true,否则 false,n 是 nonzero 的意思 |
-z | 路径存在且大小为零则返回 true,否则 false,z 是 zero 的意思 |
-L/-h | 路径存在且是链接则返回 true,否则 false,L 是 link 的意思 |
-r | 路径存在且有 read 权限则返回 true,否则 false,r 是 read 的意思 |
-w | 路径存在且有 write 权限则返回 true,否则 false,w 是 write 的意思 |
-x | 路径存在且有 execute 权限则返回 true,否则 false,x 是 execute 的意思 |
if [ -e $a ]; then echo "exist $a"; fi
if [ -d $a ]; then echo "exist directory $a"; fi
if [ -f $a ]; then echo "exist file $a"; fi
if [ -n $a ]; then echo "$a is not None"; fi
if [ -z $a ]; then echo "$a is None"; fi
if [ -L $a ]; then echo "exist link $a"; fi
if [ -r $a ]; then echo "$a has read access"; fi
if [ -w $a ]; then echo "$a has write access"; fi
if [ -x $a ]; then echo "$a has execute access"; fi
1.2 文件比较
test 命令也可以用于两个文件的比较。
| 函数 | 意义 |
|---|---|
patha -nt pathb | patha 修改时间比 pathb 新则返回 true,否则 false,nt 是 newer than 的意思 |
patha -ot pathb | patha 修改时间比 pathb 旧则返回 true,否则 false,ot 是 older than 的意思 |
patha -ef pathb | patha 和 pathb 有相同 device 和 inode number 则返回 true,否则 false |
if test $a -nt $b; then echo "$a is newer than $b"; fi
if test $a -ot $b; then echo "$a is older than $b"; fi
1.3 整数比较
下面针对的是整数判断,如果不是整数,则会报错。
| 函数 | 意义 |
|---|---|
-eq | 两整数相等则返回 true,否则 false,eq 是 equal 的意思,若输入不是俩整数,则报错 |
-gt | 两整数前者大于后者则返回 true,否则 false,gt 是 greater than 的意思,若输入不是俩整数,则报错 |
\> | 含义同 -gt,为了和重定向符号区分,则需要转义 |
-lt | lt 是 less than 的意思 |
\< | 同 -lt |
-ge | ge 是 greater eqaul 的意思,注意没有 \>= 这种写法 |
-le | le 是 less eqaul 的意思,注意没有 \<= 这种写法 |
if test $a -eq $b; then echo "$a eqals $b"; fi
1.4 字符串不相等判断
= 和 != 针对字符串。字符串完全相同则是相等,有一点不同则是不等。
| 函数 | 意义 |
|---|---|
= | 两字符串相同则返回 true,否则 false,判断字符串的等号左右都是有空格的 |
!= | 两字符串不同则返回 true,否则 false |
if test $a = $b; then echo "$a eqals $b"; fi
2. 分支结构
就是条件判断,在不同条件下执行不同的操作。常见有 if else,do while,case esac 这几种。
2.1 if else 结构
if condition; then xxx; fi
if condition; then xxx; else yyy; fi
if condition_1; then xxx; elif condition_2;then yyy; else zzz; fi
2.2 case esac 结构
如果有多个选项,可以用一堆 if elif else,也可以用 case esac 的结构。这个和 c 语言中的 switch case 是一样的。不过这个 esac 是个什么鬼?看看 if 结尾的 fi 就能大悟了。🐶
语法如下:
case $x in
1) echo "select 1";;
2) echo "select 2";;
3) echo "select 3";;
*) echo "select nothing";;
esac
最后的星号 * 表示啥也没有选到,默认值。最后两个分号(;;)是跳出当前 case esac 的意思,和其它语言中的 break 很相似。不过 shell script 本身就是有 break 和 continue 关键字的,和 c 语言中的关键字是一样的。
3. 循环结构
常见的循环结构有 for、while、until 三种:
for x in xxxx;
do
xyz_operation
done
while condition:
do
xyz
done
until condition
do
xyz
done
如果要一直执行,则可以使用 while true 死循环一直执行。
continue 是跳出当前循环,继续下一次循环的意思。break 是跳出整个循环。
当然 continue 和 break 都可以在后面接一个数字 n,表示是跳出当前第 n 层循环的意思。
4. 条件逻辑运算
4.1 分支中的条件运算
Shell 中表达式的结果可以进行与或非逻辑连接:
| 函数 | 含义 |
|---|---|
-a/&& | 逻辑与 |
-o/|| | 逻辑或 |
! | 逻辑非 |
if [ x -eq 5 ] && [ y -eq 6]; then echo "help"; fi
if test x -eq 5 && test y -eq 6; then echo "help"; fi
if ![ x -eq 5 ]; then echo "help"; fi
4.2 条件级连运算
对于命令也可以进行逻辑运算。
command_1 && command_2
这里还有一个好处,如果 command_1 已经返回逻辑假,则 command_2 就可以不执行了。
if [ ! -d ${path1} ]; then
mdkir -p ${path1}
fi
上面的写法就可以简写:
[ ! -d ${path1} ] && mkdir -p ${path1}
同样,对于或运算而言,如果第一个条件满足,后面的就不会执行了。这样的写法可以使代码更加简洁。
5. 小结
本文先介绍了 Shell 中的 test 命令,用于判断各种情况,然后介绍了 Shell 中的分支循环语法,以及条件级连运算。