- if-then
if command then commands fi
bash shell中的if语句运行在if行定义的命令. 如果命令突出状态时0, 将执行then后面的命令. 如果命令的退出状态时0以外的其他值,那么then后面的命令将不会执行.#!/bin/bash
# testing the if statement if date echo "it worked" fi
echo "we're outside of the if statement"
# 输出: it worked ; we're outside of the if statement
if语句行使用 grep 命令搜索/etc/passwd文件,查看系统是否正在使用一个特定的用户名.如果一个用户拥有该登录名,脚本会显示一些文本,然后列出用户HOME目录下的bash文件. 如果变量testuser设置成系统中不存在的一个用户,什么都不会列出
#!/bin/bash # testing multiple commands in the then section testuser=root if grep $testuser /etc/passwd then echo The bash file for user $testuser are: ls -a /home/testuser/.b* fi
- if-then-else
if command then commands
else
commands fi
如果 if 语句行的命令返回的状态码为0, 就会执行在 then 部分列出的命令, 就像在普通的 if-then 语句中一样.如果if语句行的命令返回非零退出状态码,bash shell 将会执行 else 部分的命令
#!/bin/bash # testing the else section
testuser=badtest
if grep $testuser /etc/passwd
then
echo The files for user $testuser are:
ls -a /home/$testuser/.b*
else
echo "The user name $testuser doesn't exxist on this system"
fi
输出: The user name badtest doesn't exist on this system
- 嵌套 if 语句
if command1
then
commed2
elif commed2
then
more commands
elif commed3
then
more commands
fi
elif语句行提供另一条要评估的命令,与原始的if语句行相似. 如果elif命令返回的退出状态码为 0, bash 执行第二个then语句部分的命令
命令块的执行依赖于哪条命令返回的退出状态码为0. bash shell 会按顺序执行 if 语句, 只有第一个返回0退出状态的命令会导致then部分命令被执行.
- test
提供一种检测 if-then 语句中不同条件的方法. 如果 test 命令中列出的条件评估值为 true, test 命令以0 退出状态码退出, 这使 if-then语句使用与其他编程语言中的 if-then 语句一样的方法运行. 如果条件为 false, 则 test 命令退出, 使得 if-then语句失败
test condition # condition是一系列test命令评估的参数和值. 在if-then语句中使用时, test命令如下所示 if test condition then commands fi # bash shell 提供一种在 if-then 语句中声明 test 命令的另一种方法: if [ condition ] then commands fi # 方括号定义在test命令中使用的条件.
# 注意, 在前半个方括号的后面和后半个方括号的前面必须都有一个空格,否则会得到错误信息 # test命令能评估一下3类条件: 1.数值比较, 2.字符串比较, 3.文件比较
1) 数值比较
#!/bin/bash # using numeric test comparisons var1=10 var2=11 if [ $var -gt 5 ] then echo "The test value $val1 is greater than 5" fi if [ $val1 -eq $val2 ] then echo "The values are equal" else echo "The values are different" fi # 第一个测试条件: if [ $val1 -ft 5 ] 测试变量 val1 的值是否大于5 # 第二个 test 条件: if [ $val1 -eq $val2 ] 测试变量val1的值是否等于变量val2的值 # 输出: The test value 10 is greater than 5 ; The values are different
# -----------------------------------------------------------------------
#!/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
# 输出: The test value is 3.333 ; [: 3.333: integer expression expected
当使用 bash 计算器来生成一个浮点值, 并将它存储在变量 val1 中, bash shell 将无法处理成功.
bash shell 只能处理整数数字, 在面向数值函数(如数值测试条件)中不起作用.
2) 字符串比较
# 1.字符串相等 ( 比较字符串是否相等时, 测试比较将所有标点符号和大写都考虑在内 ) #!/bin/bash # testing string equality testuser=rich if [ $USER = $testuser ] then echo "Welome $testuser" else echo "This isn't $testuser" fi # rich 登录 输出: Welcome rich # baduser登录 输出: This isn't baduser # ---------------------------------- # 2.字符串顺序 # 问题: 1.大于和小于符号一定要转义, 否则shell会将他们当作重定向符号,将字符串值看作文件名; 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 # baseball is greater than hockey # 同时当前目录下生成了一个名为 hockey 的文件 # 脚本将大于号理解为输出重定向,所以创建了一个 hockey 文件. 由于重定向成功完成,所以测试命令返回突出状态代码 0 , if 语句认为事情已成功完成. 要解决这个问题,需要适当转义大于号 # 当字符串中存在大小写字母时, test命令使用标准的 ASCII 排序 #------------------------------------------------------- # 3.字符串大小 #!/bin/bash # testing string length val1=testing val2='' if [ -n $val1 ] then echo "The string '$vall' 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 [ -z $val3 ] then echo "The string '$val3' is empty" else echo "The string '$val3' is not empty" fi # 输出: The string 'testing' is not empty ; The string '' is empty ; The string '' is empty # if [ -n $val1 ] 确定变量val1的长度是否为非零值,如果是非零值,那么将处理then部分 # if [ -z $val2 ] 确定变量val2的长度是否为0,,如果是0, 那么将处理then部分; # if [ -z $val3 ] 确定变量val3的长度是否为0,未定义,所以长度为零
警告: 空变量和没有初始化的变量可能会对shell脚本测试产生灾难性的影响.如果不确定变量的内容, 在数值比较或者字符串比较中使用它之前, 最好使用 -n 后者 -z 测试一下它是否有值
3) 文件比较
test命令能够测试Linux文件系统上的文件状态和路径
3.1 检查目录 [ -d ]
-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
3.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 ] 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.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 ] then echo ".bash_history is a file!" fi fi else echo "Sorry, the object doesn't exist" fi
3.4 是否能读 [ -r ]
#!/bin/bash #testing if you can read a file pwfile=/etc/shadow #first, test if 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 nuable to read the $pwfile file" fi else echo "Sorry, the file $file doesn't exist" fi
3.5 检查空文件 [ -s ]
#!/bin/bash # testing if a file is empty file=t15test touch $file if [ -s $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 ] then echo "The $file file has data in it" else echo "The $file is still empty" fi
3.6 检查是否能够向文件中写入数据 [ -w ]
#!/bin/bash # checking if a file is writeable logfile=$HOME/t16test touch $logfile chmod u-w $logfile now=`date +%Y%d-%H%M` if [ -w $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
3.7 检查是否能够运行文件 [ -x ]
#!/bin/bash # testing file execution if [ -x test16 ] then echo "You can run the script:" ./test16 else echo "Sorry, you are unable to execute the script" fi
3.8 检查所有权 [ -O ] (大写字母O)
#!/bin/bash # check file ownsership if [ -O /etc/passwd ] then echo "You're the owner of the /etc/passwdd file" else echo "Sorry, you're not the owner of the /etc/passwd file" fi
# -G 比较检查文件的默认组, 如果它与用户的默认组相匹配,它就成功. 只检查默认组,而不检查用户的所有组
3.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
# 如果比较的文件不存在, 只返回一个失败条件
- 复合条件检查
if-hen语句可以使用布尔逻辑来合并检查条件, 可以 使用两个布尔操作符:
[ condition1 ] && [ condition2 ] [ condition1 ] ||| [ condition2 ] # 第一个布尔操作使用 AND 布尔操作符来合并两个条件,两个条件必须都满足才能执行then部分 # 第二个布尔操作使用OR布尔操作符来合并两个条件.如果任意一个条件评估为 true ,name就会执行 then 部分.
#!/bin/bash # testing compound comparisons if [ -d $HOME ] && [ -w $HOME/test_sh/testing ] then echo "The file exists and you can write to it" else echo "I can't write to the file" fi
- if-then的高级特征 ( 双圆括号表示数学表达数 / 双方括号表示高级字符串处理函数 )
1) 使用双圆括号
双圆括号命令允许在比较中包含高级数学公式. test 命令只允许在比较总进行简单的算数操作. 双圆括号命令提供更多的数学符号,这些符号是其他语言程序员习惯使用的符号. 双圆括号命令的格式是: (( expression ))
术语 expression 可以是任何的数学赋值表达式或数学比较表达式. 除了 test 命令使用的标准数学操作符,下图显示了在双括号命令中可以使用的其他操作符列表
可以在if语句中使用双圆括号命令,也可以使用普通命令在脚本总进行赋值
#!/bin/bash # using double parenthesis val1=10 if (( $val1 ** 2 > 90 )) then (( val2 = $val1 ** 2 ))
echo "The square of $val1 is $val2" fi
# 在双圆括号内的表达式中,不必转义大于号. 这是双圆括号提供的另一个高级功能
2) 双拥双方括号
双方括号命令为字符串比较提供高级功能. 双方括号命令的格式是: [[ expression ]]
双方括号包围的 expression 使用在 test 命令中使用的标准字符串比较. 但是它提供了 test 命令没有的另一个功能, 即模式匹配. 在模式匹配中,可以定义与字符串相匹配的正则表达式
#!/bin/bash # using pattern matching if [[ $USER == r* ]] then echo "Hello $USER" else echo "Sorry, I don't know you" fi
- case
case命令将制定的变量与不同的模式进行比较.如果变量与模式匹配, shell 执行为该模式制定的命令. 可以在一行中列出多个模式, 使用竖条操作符将每个模式分开. 星号是与任何列出的模式都不匹配的所有值.
#!/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
case命令提供了一种为每个可能的变量值制定不同选项的更清楚的方法
小结:
结构化命令允许改变 shell 脚本中的普通执行流. 最基本的结构化命令是 if-then 语句.该语句允许评估一条命令, 并给予评估命令的结果执行其他命令.
如果执行的命令也失败了,可以扩展if-then语句以包含bash shelll 执行的一组命令. 只有当被估计的命令返回非零退出状态码时, if-then-else 语句才允许执行命令.
也可以使用elif语句将if-then-else语句连接起来. elif 与使用 else if 语句等同, 如果被估计的原始命令失败,可以提供额外的检查.
在大多数脚本中, 不是想估计一条命令, 而是想估计一个条件, 列如数值`字符串的内容, 或者文件或目录的状态. test 命令提供评估所有这些条件的一种简单的方法.如果条件评估为 true, test 命令就为 if-then 语句生成一个零退出状态码. 如果条件评估为 false, test 命令会为 if--then 语句生成一个非零退出状态代码.
方括号是一个特殊的bash命令,他是test命令的同义词.在if-then语句中可以使用方括号包围测试条件, 来检查数字, 字符串和文件条件.
双圆括号命令允许使用附加操作符执行高级数学评估, 双方括号允许执行高级字符串模式匹配评估.
case命令,执行多条 if-then-else 命令并在列表中检查单个变量值的快速方法