跳转至

Shell结构化命令

概要: 学习Shell(1) 结构化指令,if-then, test, case

创建时间: 2022.08.01 23:07:13

更新时间: 2023.08.16 22:32:26

本文结构

Shell结构化命令.png

if-then语句

if-then语句

基本语法

Bash
1
2
3
4
if cmd
then
    cmds
fi
示例
Bash
1
2
3
4
5
6
#!/bin/bash
if pwd
then
    echo "OK!"
    echo "It worked"
fi
image.png
注意

  1. if 后的条件判断语句 cmd 成功结束(退出码为0)后,将执行 then 后的 cmds 语句
  2. cmds 语句可以包含多条shell命令
  3. 以上 if-then 语法还可以写为如下形式
    Bash
    1
    2
    3
    if cmd; then
        cmds
    fi
    

if-then-else语句

基本语法

Bash
1
2
3
4
5
6
if cmd
then
    cmds1
else
    cmds2
fi
在上面的语法中,如果 if 后的 cmd 返回状态码0,那么执行 then 部分语句。但如果返回非零状态码,将会执行 else 部分的命令。
Bash
1
2
3
4
5
6
7
8
#!/bin/bash
testUser=NoSuchUser
if grep $testUser /etc/passwd
then
    echo "Find user $testUser!"
else
    echo "Not found user $testUser."
fi
image.png

嵌套if语句

下面的脚本用于检测用户是否存在系统中,如果不存在系统中的话,其目录有无被清理。

Bash
#!/bin/bash
testUser=NoSuchUser
if grep $testUser /etc/passwd
then
    echo "Find user $testUser!"
else
    echo "Not found user $testUser."
    if ls -d /Users/$testUser
    then
        echo "However, $testUser has a directory!"
    fi
fi
image.png
但上面的脚本使用嵌套 if 的方式,并不便于维护,推荐使用如下的 if-elif-fi 形式(else语句可选)
Bash
1
2
3
4
5
6
7
8
9
if cmd1
then
    cmds1
elif cmd2
then
    cmds2
else
    cmds3
fi
改写后的脚本如下
Bash
#!/bin/bash
testUser=NoSuchUser
if grep $testUser /etc/passwd
then
    echo "Find user $testUser!"
elif ls -d /Users/$testUser
then
    echo "Not found user $testUser."
    echo "However, $testUser has a directory!"
fi

test语句

在普通的 if 语句中,if-then只能测试命令退出状态码,并不支持如数学运算等其他操作,不过 test 语句可以测试条件语句,语法如下

Bash
test condition
if-then语句中表示为
Bash
1
2
3
4
if test condition
then
    cmds
fi
或者写为如下形式
Bash
1
2
3
4
if [ condition ]
then
    cmds
fi
conditiontest 命令要测试的一系列参数和值
举例如下,可以使用 test 判断是否为空字符串
Bash
1
2
3
4
5
6
7
8
#!/bin/bash
str="string"
if test $str
then
    echo "True"
else
    echo "False"
fi
image.png

数值比较

参考下表
image.png
简单的测试脚本如下

Bash
1
2
3
4
5
6
#!/bin/bash
x=5
if [ $x -gt 3 ]
then
    echo "x >= 3"
fi
image.png
注意:bash shell 只能处理整数

字符串比较

参考下表
image.png

字符串相等比较

Bash
1
2
3
4
5
6
7
#!/bin/bash
testUser=lzwang

if [ $USER = $testUser ]
then
    echo "Welcome $testUser"
fi
image.png

字符串顺序比较

Bash
1
2
3
4
5
6
7
8
9
#!/bin/bash
var1=baseball
var2=pingpong
if [ $var1 \> $var2 ]
then
    echo "$var1 is greater than $var2"
else
    echo "$var1 is less than $var2"
fi
image.png
注意

  1. 大于和小于号必须转义,否则shell将把它们作为重定向符号,且把字符串值当作文件名
  2. 不同字母,越靠后越大
  3. 相同字母,大写字母比小写字母(和 sort 命令相反)

字符串大小比较

Bash
#!/bin/bash
var1=test
var2=''

if [ -n $var1 ]
then
    echo "String '$var1' is not empty"
fi

if [ -z $var2 ]
then
    echo "String '$var2' is empty"
fi

if [ -z $var3 ]
then
    echo "String '$var3' is empty"
fi
image.png
注意

  1. 未定义过的变量在shell中长度为0

文件比较

image.png

检查对象是否存在和类型

Bash
#!/bin/bash
item=$HOME
if [ -e $item ]
then
    echo "item $item does exist"
    if [ -d $item ]
    then
        echo "item $item is a directory"
    elif [ -f $item ]
    then
        echo "item $item is a file"
    fi
else
    echo "item $item does not exist"
fi
image.png

检查空文件

Bash
1
2
3
4
5
6
7
8
9
#!/bin/bash
item=$HOME/playground/test_file
touch $item
if [ -s $item ]
then
    echo "item $item has data"
else
    echo "item $item has no data"
fi
image.png
注意:当被检查文件有数据时,-s 返回值为真

检查文件权限

下面的脚本检测文件的读写和执行权限
image.png

Bash
#!/bin/bash
item=$HOME/playground/test_file

if [ -r $item ]
then
    echo "$item is readable"
fi

if [ -w $item ]
then
    echo "$item is writable"
fi

if [ -x $item ]
then
    echo "$item is executable"
fi
image.png

检查文件归属

下面的脚本检测文件是否属于当前用户或者当前用户组

Bash
#!/bin/bash
item=$HOME/playground/test_file

if [ -O $item ]
then
    echo "$item is owned by $USER"
fi

if [ -G $item ]
then
    echo "$item is owned by $USER group"
fi
image.png

检查文件日期

Bash
#!/bin/bash
file2=$HOME/playground/testfile2
file3=$HOME/playground/testfile3

if [ $file3 -nt $file2 ]
then
    echo "$file3 is newer than $file2"
fi

if [ $file2 -ot $file3 ]
then
    echo "$file2 is old than $file3"
fi
image.png
注意,在比较文件时间戳时,-nt 表示 newer than,-ot 表示 older than

复合条件测试

Bash
1
2
3
4
5
# and
[ condition1 ] && [ condition2 ]

# or
[ condition1 ] || [ condition2 ]
示例略

双圆括号

双圆括号主要用于高级数学表达式,提供了更多的运算方式,如下表所示
image.png

Bash
1
2
3
4
5
6
7
#!/bin/bash
var1=10
if (( $var1 ** 2 > 90 ))
then
   (( var2 = $var1 ** 2 ))
   echo "The square of $var1 is $var2"
fi
image.png

双方括号

双方括号提供了高级字符串比较表达式,也称为模式匹配

Bash
1
2
3
4
5
#!/bin/bash
if [[ $USER == lz* ]]
then
    echo "Hello, $USER"
fi
image.png

case语句

case 语句用于简化过多的 elif 语句,语法模式如下

Bash
1
2
3
4
5
case variable in
pattern1 | pattern2) commands1;; 
pattern3) commands2;;
*) default commands;;
esac
简单示例如下
Bash
1
2
3
4
5
6
7
8
9
#!/bin/bash
case $USER in
daidai | duouo)
    echo "Welcome, guest $USER";;
lzwang)
    echo "Welcome, master $USER";;
*)
    echo "$USER has no permission to visit.";;
esac
image.png
注意

  1. case 命令将指定的变量与不同的模式相匹配,如果匹配则执行此模式下指定的命令
  2. 可以通过竖线操作符在一行中分隔出多个模式,只要有一个匹配上就执行此组模式下的命令
  3. 最终的星号捕获其他所有与已知模式不匹配的值

参考