Shell Tutorial 02

Switch and loop in Shell, with `test` and `if else`. Modified: 2023-10-27 20:01:58 Created: 2021-08-22 09:50:08 Tags: #linux #shell

分支循环是编程语言重要结构,它使得计算机源源不断地给搬砖。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 pathapathb有相同 device 和 innode 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 ge 是 less eqaul 的意思,注意没有\<=这种写法
if test $a -eq $b; then echo "$a eqals $b"; fi

1.4 字符串不相等判断

=!=针对字符串。字符串完全相同则是相等,有一点不同则是不等。

函数 意义|
= 两字符串相同则返回 true,否则 false,判断字符串的等号左右都是有空格的
!= 两字符串不同则返回 true,否则 false,gt 是 greater than 的意思,若输入不是俩整数,则报错
if test $a = $b; then echo "$a eqals $b"; fi

2 分支结构

就是条件判断,在不同条件下执行不同的操作。常见有if elsedo whilecase 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 本身就是有breakcontinue关键字的,和 c 语言中的关键字是一样的。

3 循环结构

常见的循环结构有forwhileuntil三种:

for x in xxxx;
do
xyz_operation
done
while condition:
do
xyz
done
until condition
do
xyz
done

如果要一直运行,则可以使用while true死循环一直运行。

continue是跳出当前循环,继续下一次循环的意思。 break是跳出整个循环。

当然continuebreak都可以在后面接一个数字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}

同样,对于或运算而言,如果第一个条件满足,后面的就不会执行了。这样的写法可以使代码更加简洁。

总结

本文介先绍了 Shell 中的test命令,用于判断各种情况,然后介绍了 Shell 中的分支循环语法,以及条件级连运算。