Skip to content

使用结构化命令

许多的程序要求对shell命令进行一些逻辑化的控制, 这些命令称为结构化命令

使用if-then命令

bash
if command
then 
	commands
fi

会运行if后面的哪那一个命令, 如果退出的状态码是0(运行成功), 就执行then

fi标志语句的结束

bash
if command; then
	commands
fi

示例: 查找用户是否存在

bash
  1 #!/bin/bash                                                                           
  2 testuser=jiao
  3 if grep $testuser /etc/passwd
  4 then
  5     echo "This is my first command"
  6     echo "second"
  7     echo "Third"
  8     ls -a /home/$testuser
  9 fi

if-then-else语句

bash
if command
then 
	commends
else
	commands
fi
bash
  1 #!/bin/bash                                                                           
  2 testuser=NoSuchUser
  3 if grep $testuser /etc/passwd
  4 then
  5     echo "The bash file for user $testuser are:"
  6     ls -a /home/$testuser
  7     echo
  8 else
  9     echo "The user $testuser does not exit on this system"
 10 fi
 
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ test4.sh 
The user NoSuchUser does not exit on this system

嵌套if

bash
  1 #!/bin/bash                                                                           
  2 testuser=NoSuchUser
  3 if grep $testuser /etc/passwd
  4 then
  5     echo "The bash file for user $testuser are:"
  6     ls -a /home/$testuser
  7     echo
  8 else
  9     echo "The user $testuser does not exit on this system"
 10     if ls -d /home/NoSuchUser
 11     then echo "Hower $testuser has a directory"
 12     fi
 13 fi
bash
if command1
then
	commands
elif command2
then 
	more commands
fi
bash
  1 #!/bin/bash                                                                           
  2 testuser=NoSuchUsers
  3 if grep $testuser /etc/passwd
  4 then
  5     echo "The bash file for user $testuser are:"
  6     ls -a /home/$testuser
  7     echo
  8 elif ls -d /home/$testuser
  9     echo "The user $testuser does not exit on this system"
 10     then echo "Hower $testuser has a directory"
 11 else
 12     echo "The user $testuser dose not exit in this system"
 13     echo "And don't have a dictory "
 14 fi

test命令

if-then语句不能测试命令退出状态码之外的条件

test命令提供了在if-then语句中测试不同条件的途径。如果test命令中列出的条件成立,test命令就会退出并返回退出状态码0。这样if-then语句就与其他编程语言中的if-then语句以类似的方式工作了

bash
test condition

使用在if-then语句之中

bash
if test condition
then 
	commands
fi

如果不写test的condition就会以0退出

bash
  1 #!/bin/bash                                                                           
  2 if test 
  3 then echo "No expression return a true"
  4 else  echo "return a False"
  5 fi
  6 

jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ test7.sh 
return a False

可以用来检测变量之中是不是有变量

bash
#!/bin/bash 
my_variable="Full" 
if test $my_variable
then
	echo "The $my_variable expression returns a True" 
else 
	echo "The $my_variable expression returns a False" fi

还有另一种测试的方法

bash
if [ condition ]
then
	condition
fi

**注意:**第一个方括号之后和第二个方括号之前必须加上一个空格,否则就会报错

test命令可以判断三类条件:

  • 数值比较字
  • 符串比较
  • 文件比较

数值比较

比较描述
n1 -eq n2检查n1是否与n2相等
n1 -ge n2检查n1是否大于或等于n2
n1 -gt n2检查n1是否大于n2
n1 -le n2检查n1是否小于或等于n2
n1 -lt n2检查n1是否小于n2
n1 -ne n2检查n1是否不等于n2
  • 数值变量可以使用在数值或变量之上
bash
  1 #!/bin/bash                                                                           
  2 value1=10
  3 value2=11
  4 if [ $value1 -gt 5 ]
  5 then echo "the test value $value1 is greater than 5"
  6 fi
  7 if [ $value1 -eq $value2 ]
  8 then
  9     echo "The value are equal"
 10 else
 11     echo "The value are different"
 12 fi
bash
#!/bin/bash 
# Using floating point numbers in test evaluations 
value1=5.555 
echo "The test value is $value1"
if [ $value1 -gt 5 ] 
then
	echo "The test value $value1 is greater than 5" 
fi

jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ test9.sh 
The test value is 5.555
./test9.sh: 8 行: [: 5.555:需要整数表达式

bash shell只能处理整数, 但是在$显示的时候没有问题, 在基于数字的函数中就不行了

字符串比较

比较描述
str1 = str2检查str1是否和str2相同
str1 != str2检查str1是否和str2不同
str1 < str2检查str1是否比str2小
str1 > str2检查str1是否比str2大
-n str1检查str1的长度是否非0
-z str1检查str1的长度是否为0

字符串相等

bash
  1 #!/bin/bash                                                                           
  2 # 测试字符串是否相等
  3 testuser=jiao
  4 if [ $testuser = $USER ]
  5 then
  6     echo "Welcome $testuser" 
  7 fi

字符串顺序

  • 大于号和小于号必须转义,否则shell会把它们当作重定向符号,把字符串值当作文件名;
  • 大于和小于顺序和sort命令所采用的不同
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ cat test11.sh 
#!/bin/bash
val1=baseball
val2=honkey
if [ $val1 > $val2 ]
then echo "$val1 is greater than $val2"
else echo "$val1 is less than $val2"
fi

jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ test11.sh 
baseball is greater than honkey
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ ls
honkey  test10.sh  test2.sh  test4.sh  test6.sh  test8.sh  test.py
test1   test11.sh  test3.sh  test5.sh  test7.sh  test9.sh

把大于号解释为输出重定向

要解决这个问题应该使用转义字符

bash
  1 #!/bin/bash                                                                           
  2 val1=baseball
  3 val2=honkey
  4 if [ $val1 \> $val2 ]
  5 then echo "$val1 is greater than $val2"
  6 else echo "$val1 is less than $val2"
  7 fi

排序的时候会认为是大写字母小于小写字母

比较测试中使用的是标准的ASCII顺序,根据每个字符的ASCII数值来决定排序结果。sort命令使用的是系统的本地化语言设置中定义的排序顺序。对于英语,本地化设置指定了在排序顺序中小写字母出现在大写字母前

字符串的大小

bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ cat test12.sh 
#!/bin/bash
# 测试字符串的长度
val1=testing
val2=''
if [ -n $val1 ]
then echo "The string '$val1' is not empty"
else echo "The string '$val1' is empty"
fi
if [ -z $val2 ]
then echo "The string '$val2' is empty"
else echo "The string '$val2' is not empty"
fi
if [ -n $val3 ]
then echo "The string '$val3' is not empty"
else echo "The string '$val3' is empty"
fi
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ test12.sh 
The string 'testing' is not empty
The string '' is empty
The string '' is not empty

没有定义的变量会被认为是空的, 但是没有定义的或空的字符串会对脚本产生巨大的影响, 所以最好进行检查

文件比较

允许你测试文件目录的状态

比较描述
-d file检查file是否存在并是一个目录
-e file检查file是否存在
-f file检查file是否存在并是一个文件
-r file检查file是否存在并可读
-s file检查file是否存在并非空
-w file检查file是否存在并可写
-x file检查file是否存在并可执行
-O file检查file是否存在并属当前用户所有
-G file检查file是否存在并且默认组与当前用户相同
file1 -nt file2检查file1是否比file2新
file1 -ot file2检查file1是否比file2旧

检查目录

打算把文件写入某一个目录或者切换到某一个目录最好检查目录是否存在

bash
  1 #!/bin/bash                                                                           
  2 jump_dictory=/home/jiao
  3 if [ -d $jump_dictory ]
  4 then
  5  echo "This $jump_dictory exists"
  6  cd $jump_dictory
  7  ls
  8 else
  9     echo "This $jump_dictory dictory does not exit"
 10 fi
 
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ test13.sh 
This /home/jiao exists
01_Python  公共的  模板  视频  图片  文档  下载  音乐  桌面  Makefile  snap

检查对象是否存在

bash
if [ -e $location ] 
then
...

检查文件

bash
if [ -f $location ] 
then
...

检查是否可读

bash
  1 #!/bin/bash                                                                           
  2 pwfile=/etc/shadow
  3 if [ -f $pwfile ]
  4 then
  5     if [ -r $pwfile ]
  6         then tail $pwfile
  7     else echo "Sorry I am un able to read the $pwfile"
  8     fi
  9 else
 10     echo "Sory the file $pwfile does'n exit"
 11 fi

jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ test14.sh # 没有权限
Sorry I am un able to read the /etc/shadow
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ sudo ./test14.sh # 有权限
colord:*:18912:0:99999:7:::
geoclue:*:18912:0:99999:7:::
pulse:*:18912:0:99999:7:::
gnome-initial-setup:*:18912:0:99999:7:::
hplip:*:18912:0:99999:7:::
gdm:*:18912:0:99999:7:::
jiao:$6$apS9G8HD6duUAyqr$2e81915XsZW02XwXRuyWzo9GVElzwo3kr7X9JUDUlPMDdDCuiJT7mqbV1y6rc1C1EFcF1HeS6dt5dvFUv0Y0/1:19062:0:99999:7:::
systemd-coredump:!*:19063::::::
sshd:*:19064:0:99999:7:::
test:$6$57tVSKi5Obpm5cUj$cPcjBFM7iQtsLMOPMj8wsGvLpLGWEQDNDKnm.jDwOAE3RmiKbcIG7FqPF0924JUarmKU2yKy.L6BIwuG8Lrnt/:19207:0:99999:7:::

检查空文件

bash
  1 #!/bin/bash                                                                           
  2 file_name=./test_file
  3 if [ -f $file_name ]
  4 then
  5     if [ -s $file_name ]
  6     then
  7         echo "The file $file_name is existing and date in it"
  8         echo "Will not remove it"
  9     else
 10         echo "The file $file_name is empty and will remove"
 11         rm $file_name
 12     fi
 13 else
 14     echo "the file dose not exit"
 15 fi


jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ test15.sh # 没有创建的时候
the file dose not exit
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ touch test_file # 创建空文件
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ test15.sh 
The file ./test_file is empty and will remove
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ ls
honkey  test10.sh  test12.sh  test14.sh  test2.sh  test4.sh  test6.sh  test8.sh  test.py
test1   test11.sh  test13.sh  test15.sh  test3.sh  test5.sh  test7.sh  test9.sh
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ touch test_file #创建非空文件
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ vim test_file 
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ test15.sh 
The file ./test_file is existing and date in it
Will not remove it

检查文件是否可写

bash
if [ -w $location ] 
then
...

检查文件是否可执行

bash
if [ -x test16.sh ] 
then    
echo "You can run the script: "    
./test16.sh

检查文件的所属关系

bash
if [ -O /etc/passwd ] 
then    
	echo "You are the owner of the /etc/passwd file" 
else    
echo "Sorry, you are not the owner of the /etc/passwd file" 
fi

比较文件所属的组

bash
#!/bin/bash
check file group test 
if [ -G $HOME/testing ] 
then    
	echo "You are in the same group as the file" 
else    
	echo "The file is not owned by your group" 
fi

只会比较用户的默认组, 不会比较其他的组

检查日期文件

在编写软件安装脚本的时候有用, 判断是不是新的版本

-nt比较会判定一个文件是否比另一个文件新。如果文件较新,那意味着它的文件创建日期更近。-ot比较会判定一个文件是否比另一个文件旧。如果文件较旧,意味着它的创建日期更早

bash
  1 #!/bin/bash
  2 if [ test2.sh -nt test5.sh ]
  3 then echo "test2 is newer than test5"
  4 else echo "test2 is older than test5"
  5 fi
  6 if [ test7.sh -ot test5.sh ]
  7 then echo "test7 is older than test5"
  8 else echo "test7 is nower than test5"                                                 
  9 fi

jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ test16.sh 
test2 is older than test5
test7 is nower than test5

复合条件测试

有两种bool运算

  • [ condition1 ] && [ condition2 ]
  • [ condition1 ] || [ condition2 ]

if-then的高级特性

使用双括号

除了test命令使用的标准数学运算符, 双括号允许使用更高级的运算

  • ++
  • --
  • !
  • ~
  • **
  • <<
  • $>>$
  • &
  • |
  • &&
  • ||

可以在if语句中用双括号命令,也可以在脚本中的普通命令里使用来赋值

bash
  1 #!/bin/bash                                                                           
  2 if ((1+1 ==2))
  3 then echo "True"
  4 else echo "False"
  5 fi

使用双括号

可以使用针对字符串的高级操作, 比如和正则表达式进行比较

bash
  1 #!/bin/bash                                                                           
  2 if [[ $USER == j* ]]
  3 then echo "Hello $USER"
  4 else echo "GUN"
  5 fi
  
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ test18.sh 
Hello jiao

case命令

bash
case variable in 
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default commands;;
esac

将变量和不同的模式进行比较, 可以通过 | 分割出多个模式, *会匹配所有的值

bash
  1 #!/bin/bash                                                                           
  2 
  3 case $USER in
  4 jiao | dong)
  5     echo "Welcome $USER"
  6     echo "Enjoy your visit";;
  7 testing)
  8     echo "Do your test";;
  9 *)
 10     echo "Gun";;
 11 esac
 
jiao@jiao-virtual-machine:~/桌面/linux-shell/12$ test19.sh 
Welcome jiao
Enjoy your visit