使用结构化命令
有一类名,容许脚本根据变量之的条件或者其他命令的结果跳过一些命令或者循环执行这些命令。这类命令我们通常称之为结构化命令;
1、使用if-then语句
语句结构为:
if command
then
commands
fi
如果if后执行命令正确,或者返回码为0,这执行then后面的命令。如果推出状态码不是0,那么then后面的命令将不会被执行;
#!/bin/bash #testing the if statement if date then echo "it worked" fi
chmod u+x test1 ./test1
date命令执行成功,则状态返回值为0,所以执行then后面的命令;
另外一个实例:
#!/bin/bash #testing a bad command if asdfg then echo "it didn't work" fi echo "we're outside of th if statement"
chmod u+x test2 ./test2
asdfg的命令找不到,返回状态错误,则不会执行then后面的命令,直接跳到 fi 后面执行后面的echo命令。
这里运行错误信息仍然会显示出来;
then后面可以执行多条命令,如下面的实例:
#!/bin/bash # testing multiple commands in the tehn section testuser=rich if grep $testuser /etc/passwd then echo The bash files for user $testuser are: ls -a /home/$testuser/.b* fi
chmod u+x test3 ./test3
打印出teacher用户的家目录下的相关的.b*文件
if语句也可以将then写在if的同一排,如下:
if command; then
commands
fi
2、if-then-else语句
在if-then语句中,只能选择执行与否,而不能选择其他的命令来运行,这里我们就需要使用else;
if command
then
commands
else
commands
fi
if后面的command执行成功,后面就执行then后的语句,如果返回值不是0则执行else后的语句;
#!/bin/bash #testing the else section testuser=badtest if grep $testuser /etc/passwd then echo The files for user $testuser area: ls -a /home/$testuser/.b* else echo "The user name $testuser doesn't exist on this system" fi
chmod u+x test4 ./test4
因为不存在badtest用户,返回值不为0,则执行else后语句;
这样显然会更加友好
3、嵌套的if语句
如果选择运行的结果不止两种,则可以通过elif来实现多种选项的执行;
if command1
then
commands
elif command2
then
more commands
fi
上面的方式还是有些许的麻烦,在工作中,我们经常使用下面的方式:if-then-elif组:
if command1
then
command set 1
elif command2
then
command set 2
elif command3
then
command set 3
elif command4
then
command set 4
fi
命令执行,满足那个条件,则执行对应条件下的命令即可;
但是这种使用方式依然很麻烦,而我们常用的则是case语句来实现这种需求,在后面我们会详细说道;
4、test命令
test命令提供了一种检测if-then语句中不同条件的方法。如果test命令中列出的条件评估值为true,test命令以0退出转态码退出,这使if-then语句使用与其他编程语句中的if-then语句一样的方法运行。如果条件为false,则test命令退出,使得if-then与语句失败;
test用法:test condition
关联if-then的用法:
if test condition
then
commands
fi
bash shell提供了一种在if-then语句中申明test命令的另外一种用法
if [ condition ]
then
commnads
fi
[] 中定义了test的条件 condition,注意:括号里面的condition前后都必须加一个空格符;
test支持的命令评估方式有如下三种:
1、数值比较
2、字符串比较
3、文件比较
4.1、数值比较
例子:
#!/bin/bash #using numeric test comparisons val1=10 val2=11 if [ $vall -gt 5 ] then echo "The test value $val1 is greater then 5" fi fi [ $val1 -eq $val2 ] then echo "The values are equal" else echo "The values are different" fi
第一个测试条件 $val1 -gt 5 val1的值是否大于5
第二个测试条件 $val1 -eq $val2 val1的值是否等于val2的值
chmod u+x test5 ./test5
但是test数值条件有一个限制:
#!/bin/bash #testing floating point numbers val1=`echo "scale=4; 10 / 3" | bc` echo "The test value is $val1" if [ $val1 -gt 3 ] then echo "The result is larger than 3" fi
chmod u+x test6 ./test6
很显然val1输出的为一个浮点数,浮点数与整数进行运算就会出错;
4.2、字符串比较
1、字符串相等
#!/bin/bash #testing string equality testuser=rich if [ $USER = $testuser ] then echo "Welcome $testuser" fi
chmod u+x test7 ./test7
$USER使用的为当前用户,与指定的变量$testuser相同,会执行后面的echo命令;
类似的,也可以判断不相等:
#!/bin/bash #testing string equality testuser=baduser if [ $USER != $testuser ] then echo "This isn't $testuser" else echo "Welcome $testuser" fi
chmod u+x test8 ./test8
不相等则运行then后面的命令,如果相等,则运行else后面的命令;
2、字符串顺序
比较字符串大小的时候有两个问题:
*大于号和小于号一定要进行转意,不然就默认认为是重定向符号;
*大于和小于顺序与在sort命令中的顺序不同;
这里,字符串大小比较是首字母的排序;
#!/bin/bash #mis-using string comparisons val1=baseball val2=hockey if [ $val1 > $val2 ] then echo "$val1 is greater than $val2" else echo "$val1 is less than $val2" fi
chmod u+x badtest ./badtest
重定向完成,没有错误,恢复状态码0,则运行then后面的命令;
我们需要通过转意字符 \ 来解决这个问题;
#!/bin/bash #mis-using string comparisons val1=baseball val2=hockey if [ $val1 \> $val2 ] then echo "$val1 is greater than $val2" else echo "$val1 is less than $val2" fi
chmod u+x test9 ./test9
字符串的大小写的比较
#!/bin/bash #testing string sort order val1=Testing val2=testing if [ $val1 \> $val2 ] then echo "$val1 is greater than $val2" else echo "$val1 is less than $val2" fi
chmod u+x test10 ./test10
说明:小写字母要比大小字母大。
3、字符串的大小
评估一个变量是否包含数据的时候,通过-n和-z来比较就比较方便了
#!/bin/bash #testing string length val1=testing val2='' if [ -n $val1 ] #val1的长度是否为非0 then echo "The string '$val1' is not empty" else echo "The string '$val1' is empty" fi if [ -z $val2 ] #val2的长度是否为0 then echo "The string '$val2' is empty" else echo "The string '$val2' is not empty" fi if [ -z $val3 ] #没有定义$val3,所以它的长度也是0 then echo "The string '$val3' is empty" else echo "The string '$val3' is not empty" fi
chmod u+x test10 ./test10
4.3、文件比较
这是在我们脚本中最长使用的一类比较:
1、检查目录
-d 检测指定的文件是否存在于我们的系统中。
#!/bin/bash #look before you leap if [ -d $HOME ] then echo "Your HOME directory exists" cd $HOME ls -a else echo "There's a problem with your HOME directory" fi
判断用户的home目录是否存在;
2、查找对象是否存在
-e 比较能够检查文件或者目录是否存在;
#!/bin/bash #checking if a directory exists if [ -e $HOME ] #检查是否存在家目录 then echo "OK on the directory, now let's check the file" #Checking if a file exists if [ -e $HOME/testing ] #检查家目录下的testing目录是否存在 then #the file exists, append data to it echo "Appending date to existing file" date >> $HOME/testing #存在则追加数据 else #the file doesn't exist,create a new file echo "Creating new file" date > $HOME/testing #不存在则直接重定向数据到这个文件中即可 fi else echo "Sorry,you don't have a HOME directory" fi
3、检查文件
-f 用来进行比较
#!/bin/bash #check if a file if [ -e $HOME ] #判断家目录是否存在 then echo "The object exists, is it a file?" if [ -f $HOME ] #如果存在,则判断他是否是一个文件 then echo "Yes, it's a file!" else echo "No, it's not a file!" if [ -f $HOME/.bash_history ] #判断$HOME/.bash_history是否为文件 then echo "But this is a file!" fi fi else echo "Sorroy,the object doesn't exist" fi
4、是否能读
-r 判断文件是否具有刻度权限
#!/bin/bash #testing if you can read a file pwfile=/etc/shadow #first ,test is the file exists,and is a file if [ -f $pwfile ] then #now test if you can read it if [ -r $pwfile ] then tail $pwfile else echo "Sorry,I'm unable to read the $pwfile file" fi else echo "Sorry,the file $pwfile doesn't exist" fi
5、检查空文件
-s比较文件是否为空
#!/bin/bash #testing if a file is empty file=t15test touch $file if [ -e $file ] then echo "The $file file exists and has data in it" else echo "The $file exists and is empty" fi date > $file if [ -s $file ] #判断$file问价那种是否存在数据 then echo "The $file file has data in it" else echo "The $file is still empty" fi
6、检查是否能够向文件中写入数据
-w 比较确定是否有权限向文件中写入数据
#!/bin/bash #checking if a file is writeable logfile=$HOME/t16test touch $logfile chmod u-w $logfile now=`date +%Y%m%d-%H%M` if [ -w $logfile ] #判断$logfile是否有写权限 then echo "The program ran at: $now" > $logfile echo "The fist attempt succeeded" else echo "The first attempt failed" fi chmod u+w $logfile if [ -w $logfile ] then echo "The program ran at: $now" > $logfile echo "The second attempt succeeded" else echo "The second attempt failed" fi
7、检查是否能够运行文件
-x 判断文件是否具有执行权限
#!/bin/bash #testing file execution if [ -x test16 ] #判断test16文件是否具有执行权限 then echo "You can run the script:" ./test16 else echo "Sorry,you are unable to execute the script" fi
8、检查所有权
-O 比较可以容易的检查您是否是问价你的所有者
#!/bin/bash #check file ownsership if [ -O /etc/passwd ] then echo "You're the ower of the /etc/passwd file" else echo "Sorry,you're not the owner of th /etc/passwd file" fi
第一次在普通用户下检查则失败,之后切换到root用户下,就能成功;
-G 检查文件的默认组,匹配默认组匹配成功,就正确;
#!/bin/bash #check file group test if [ -G $HOME/testing ] #判断 then echo "You're in the same group as the file" else echo "The file is not owned by your group" fi
./test19 chgrp sharing $HOME/testing ./test19
9、检查文件日期
-nt 比较确定一个文件是否比另一个文件新
-ot 比较确定一个文件是否比另一个文件更旧
#!/bin/bash #testing file dates if [ ./test19 -nt ./test18] then echo "The test19 file is newer than test18" else echo "The test18 file is newer than test19" fi if [ ./test17 -ot ./test19 ] then echo "The test17 file is older than the test19 file" fi
如果正在检查的文件可以四处移动,则这个脚本就会出现问题,另一个问题是,这两个比较都不能用于检查文件是否一开始就存在。
#!/bin/bash #testing file dates if [ ./badfile1 -nt ./badfile2 ] then echo "The badfile1 file is newer than badfile2" else echo "The badfile2 file is newer than badfile1" fi
文件在不存在的时候,比较依然继续进行;
5、复合条件查找
if-then语句可以使用布尔逻辑啦进行复合条件查找:
[ condition1 ] && [ condition2 ] #这个是and
[ condition2 ] || [ condition2 ] #这个是or
#!/bin/bash #testing compound comparisons if [ -d $HOME ] && [ -w $HOME/testing ] then echo "The file exists and you can write to it " else echo "I can't write to the file" fi
6、if-then的高级特征
bash shell中最近新增加了两个比较新的功能,他们提供了可以在if-then语句中使用的高级功能:
*双圆括号表示数学表达式
*双方括号表示高级字符串处理函数
6.1、使用双圆括号
(( expression ))
可以在if语句中使用双圆括号名,也可以使用普欧婷命令再脚本中进行赋值:
#!/bin/bash #using double parenthesis val1=10 if (( $val1 ** 2 > 90 )) then (( val2 = $val1 ** 2 )) echo "The sequare of $val1 is $val2" fi
在双圆括号中不必进行符号转意;
6.2、使用双方括号
[[ expression ]] #模式匹配(pattern)
在模式匹配中,可以定义字符串相匹配的正则表达式
#!/bin/bash #using pattern matching if [[ $USER == r* ]] then echo "Hello $USER" else echo "Sorroy,I don't know you" if
7、case命令
if-then-else,选项多了以后,会比较麻烦,代码执行效率会比较低;
所以我们可以使用case语句来实现;
#!/bin/bash #looking for a possible value if [ $USER = "rich" ] then echo "Welcome $USER" echo "Please enjoy your visit" elif [ $USER = barbara ] then echo "Welcome $USER" echo "Please enjoy your visit" elif [ $USER = testing ] then echo "Special testing account" elif [ $USER = jessica ] then echo "Don't forget to logout when you're done" else echo "Sorry,you're not allowed here" fi
这样的代码运行效率比较低,每个选项都会进行比较
case语句来实现这个功能;
case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default commands;;
esac
#!/bin/bash #using the case command case $USER in rich | barbara) echo "Welcome,$USER" echo "Please enjoy your visit";; testing) echo "Special testing account";; jessica) echo "Don't forget to log off when you're done";; *) echo "Sorry,you're not allowed here";; esac