说明:本文部分内容均摘取自书籍《Linux命令行与shell脚本编程大全》,版权归原作者所有。《Linux命令行与shell脚本编程大全》(第三版)第十二章学习总结
第十二章:使用结构化命令
本章内容
使用if-then语句
嵌套if语句
test命令
复合条件测试
使用双方括号和双括号
case命令
12.1 使用if-then语句
语句格式:
if command
then
command
fi
或
if command; then
command
fi
语句说明:bash shell的if语句会运行if后面的那个命令,如果该命令的退出状态码是0(该命令执行成功),则位于then部分的命令就回被执行。如果不是0,则不执行then部分的命令,继续执行脚本中的下一个命令。fi语句表示if-then语句到此结束。
编写test1.sh脚本
#!/bin/bash
# testing the if statement
if pwd
then
echo It worked
fi
编写test2.sh脚本
#!/bin/bash
# testing a bad command
if IamNotaCommand
then
echo "It worked"
fi
echo "We are outside the if statement"
编写test3.sh脚本
#!/bin/bash
if grep $testuser /etc/passwd
then
echo "This is my first command"
echo "This is my second command"
echo "I can even put in other commands besides echo:"
ls -a /home/$testuser/.b*
fi
12.2 if-then-else语句
语句格式
if command
then
command
else
command
fi
语句说明:当if语句中的命令返回退出状态码为0时,then部分中的命令会被执行;当状态码不为0时,else部分中的命令会被执行。
编写test4.sh脚本
#!/bin/bash
# testing multiple commands in the then section
testuser=nosuchuser
if grep $testuser /etc/passwd
then
echo "This is my first command"
echo "This is my second command"
echo "I can even put in other commands besides echo:"
ls -a /home/$testuser/.b*
else
echo "The user $testuser does not exist on this system."
fi
12.3 嵌套if
要检查/etc/passwd文件中是否存在某个用户以及该用户的目录是否尚在,可以使用嵌套的if-then语句。嵌套的if-then语句位于主if-then-else语句的else代码块中。
语句格式
if command1
then
commands
elif command2
then
more commands
else
moreandmore commands
fi
语句说明:先执行command1,返回状态码为0时,执行commands,从elif到fi之间的命令则跳过。当command1返回状态码不为0时,则执行command2,command2的返回状态码为0,则执行more commands;不为0,则执行moreandmore commands。
编写test5.sh脚本
#!/bin/bash
# testing nested ifs - use elif
testuser=nosuchuser
if grep $testuser /etc/passwd
then
echo "The user $testuser exists on this system."
elif ls -d /home/$testuser
then
echo "The user $testuser dose not exist on this system."
echo "However,$testuser has a directory"
else
echo "The user $testuser dose not exist on this system."
echo "And,$testuser dose not have a directory"
fi
窍门:在elif语句中,紧跟其后的else语句属于elif代码块。它们并不属于之前的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 5
fi
12.4 test命令
命令格式:test condition
命令说明:如果test命令中列出的条件成立,test命令就回返回0,否则返回非零的状态码,这样就可以结合if-then语句使用。
语句格式
if test condition
then
commands
fi
语句说明:如果test命令的condition部分为空时,它会返回非零的退出状态码。
语句格式
if [ condition ]
then
commands
fi
语句说明:bash shell提供的另一种测试方法,第一个方括号之后和第二个方括号之前必须加一个空格。
test命令可以判断三类条件
数值比较
字符串比较
文件比较
12.4.1 数值比较
test命令的数值比较功能
n1 -eq n2:检查n1是否等于n2
n1 -gen2:检查n1是否大于或等于n2
n1 -gt n2:检查n1是否大于n2
n1 -le n2:检查n1是否小于或等于n2
n1 -lt n2:检查n1是否小于n2
n1 -ne n2:检查n1是否不等于n2
编写numberic_test.sh脚本
#!/bin/bash
value1=10
value2=11
#
if [ $value1 -gt 5 ]
then
echo "The test value $value1 is greater then 5"
fi
#
if [ $value1 -eq $value2 ]
then
echo "The values are equal"
else
echo "The values are different"
fi
bash shell只能处理整数。如果只是通过echo来显示浮点数,则没问题;如果用于数值比较,则会出错。
编写floating_point_test.sh脚本
#!/bin/bash
#
value1=5.555
#
echo "The test value is $value1"
#
if [ $value1 -gt 5 ]
then
echo "The test value $value1 is greater then 5"
fi
12.4.2 字符串比较
字符串比较测试
str1 = str2:检查str1是否和str2相同
str1 != str2:检查str1是否和str2不同
str1 < str2:检查str1是否比str2小(使用时大于符号注意转义)
str1 > str2:检查str1是否比str2大(使用时小于符号注意转义)
-n str2:检查str1的长度是否非0
-z str2:检查str1的长度是否为0
1.字符串相等性
编写test7.sh脚本
#!/bin/bash
# testing string equality
testuser=rich
#
if [ $USER = $testuser ]
then
echo "Welcome $testuser"
else
echo "This is not $testuser"
fi
编写test8.sh脚本
#!/bin/bash
# testing string equality
testuser=rich
#
if [ $USER != $testuser ]
then
echo "This is not $testuser"
else
echo "Welcome $testuser"
fi
2.字符串顺序
编写test9.sh脚本
#!/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
注意:在进行字符串比较时,使用的是标准的ASCII顺序,根据每个字符的ASCII数值来决定排序结果,大写字母被认为是小于小写字母的。但sort命令恰好相反。
说明:test命令和测试表达式使用标准的数学比较符号来表示字符串比较,而用文本代码(如:-eq,-ge等)来表示数值比较。这个细微的特性被很多程序员理解反了。如果你对数值使用了数据运算符,shell会将它们当成字符串值,可能无法得到正确的结果。
3.字符串大小
编写test10.sh脚本
#!/bin/bash
# testing string length
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 [ -z $val3 ]
then
echo "The string '$val3' is empty"
else
echo "The string '$val3' is not empty"
fi
敲门:空的和未初始化的变量会对shell脚本测试造成灾难性的影响。如果不是很确定一个变量的内容,最好在将其用于数值或字符串比较之前先通过-n或-z来测试一下变量是否含有值。
12.4.3 文件比较
test命令的文件比较功能
-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旧
1.检查目录
-d测试会检查指定的目录是否存在于系统中。如果你打算将文件写入目录或是准备切换到某个目录中,先进行测试总是件好事情
编写test11.sh脚本
#!/bin/bash
# Look before you leap
#
jump_directory=/home/zc
#
if [ -d $jump_directory ]
then
echo "The $jump_directory directory exists"
cd $jump_directory
ls
else
echo "The $jump_directory directory dose not exist"
fi
2.检查对象是否存在
-e比较允许你的脚本代码在使用文件或目录前先检查它们是否存在
编写test12.sh脚本
#!/bin/bash
# Check if either a directory or file exists
#
location=$HOME
file_name="sentinel"
#
if [ -e $location ]
then #Directory does exist
echo "OK on the $location directory."
echo "Now checking on the file, $file_name."
#
if [ -e $location/$file_name ]
then #File does exist
echo "OK on the filename"
echo "Updating Current Date..."
date >> $location/$file_name
#
else #File does not exist
echo "File does not exist"
echo "Nothing to update"
fi
#
else #Directory does not exist
echo "The $location directory does not exist."
echo "Nothing to update"
fi
3.检查文件
-e比较可用于文件和目录。要确定指定对象为文件,必须用-f比较
编写test12.sh
#!/bin/bash
# check if either a directory or file exists
#
item_name=$HOME
echo
echo "The item being checked: $item_name"
echo
#
if [ -e $item_name ]
then #Item does exist
echo "The item, $item_name, does exist."
echo "But is it a file?"
echo
#
if [ -f $item_name ]
then #Item is a file
echo "Yes, $item_name is a file."
#
else #Item is not a file
echo "No, $item_name is not a file."
fi
#
else #Item does not exist
echo "The item, $item_name, does not exist."
echo "Nothing to update"
fi
4.检查是否可读
在尝试从文件中读取数据之前,最好先测试一下文件是否可读,可以使用-r比较测试
编写test14.sh脚本
#!/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 am unable to read the $pwfile file"
fi
else
echo "Sorry, the file $pwfile does not exist"
fi
5.检查空文件
使用-s比较来检查文件是否为空,当-s比较成功时,说明文件中有数据。
编写test15.sh脚本
#!/bin/bash
# Testing if a file is empty
#
file_name=$HOME/sentinel
#
if [ -f $file_name ]
then
if [-s $file_name ]
then
echo "The $file_name file exists and has data in it."
echo "Will not remove this file."
else
echo "The $file_name file exists,but is empty."
echo "Deleting empty file..."
rm $file_name
fi
else
echo "File,$file_name,does not exist."
fi
6.检查是否可写
使用-w比较进行判断你对文件是否有可写权限
编写test16.sh脚本
#!/bin/bash
# check if a file is writable.
#
item_name=$HOME/sentinel
echo
echo "The item being checked: $item_name"
echo
#
if [ -e $item_name ]
then #Item does exist
echo "The item, $item_name, does exist."
echo "But is it a file?"
echo
#
if [ -f $item_name ]
then #Item is a file
echo "Yes, $item_name is a file."
echo "But is it writable?"
echo
#
if [ -w $item_name ]
then #Item is writable
echo "Writing current time to $item_name"
date +$H$M >> $item_name
#
else #Item is not writable
echo "Unable to write to $item_name"
fi
#
else #Item is not a file
echo "No, $item_name is not a file."
fi
#
else #Item does not exist
echo "The item, $item_name, does not exist."
echo "Nothing to update"
fi
7.检查文件是否可以执行
使用-x比较判断特定文件是否有执行权限
编写test17.sh脚本
#!/bin/bash
# testing file execution
#
if [ -x test16.sh ]
then
echo "You can run the script:"
./test16.sh
else
echo "Sorry, you are unable to execute the script"
fi
8.检查所属关系
使用-O比较测试当前用户是否是文件的属主
编写test18.sh脚本
#!/bin/bash
# eheck file ownership
#
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
9.检查默认属组关系
使用-G比较检查文件的默认组,如果它匹配了用户的默认组,则测试成功。注:-G比较只会检查默认组而非用户所属的所有组。
编写test19.sh脚本
#!/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 you group"
fi
10.检查文件日期
使用-nt比较判断一个文件是否比另一个文件新。如果文件较新,则文件的创建日期更近。
使用-ot比较判断一个文件是否比另一个文件旧。如果文件较旧,则文件的创建日期更早。
编写test20.sh脚本
#!/bin/bash
# testing file dates
#
if [ test19.sh -nt test18.sh ]
then
echo "The test19 file is newer than test18"
else
echo "The test18 file is newer than test19"
fi
if [ test17.sh -ot test19.sh ]
then
echo "The test17 file is older than the test19 file"
fi
编写test21.sh脚本
#!/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
注意:这些命令都没有检查文件是否存在,在使用这些命令之前,必须先确认文件是存在的
12.5 复合条件测试
if-then语句允许使用布尔逻辑来组合测试,格式如下
[ condition1 ] && [ condition2 ]
[ condition1 ] || [ condition2 ]
窍门:布尔逻辑是一种能够将可能的返回值简化为TRUE或FALSE的方法
编写test22.sh脚本
#!/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 connot write to the file"
fi
12.6 if-then的高级特性
12.6.1 使用双括号
命令格式:(( expression ))
命令说明:使用双括号可以在比较过程中使用高级数据表达式
双括号命令符号
val++:后自增
val--:后自减
++val:先自增
--val:先自减
!:逻辑求反
~:位求反
**:幂运算
<<:左位移
>>:右位移
&:位布尔与
|:位布尔或
&&:逻辑与
||:逻辑或
编写test23.sh脚本
#!/bin/bash
# using double parenthesis
#
var1=10
#
if (( $val1 ** 2 > 90 ))
then
(( val2 = $val1 ** 2 ))
echo "The square of $val1 is $val2"
fi
12.6.2 使用双方括号
命令格式:[[ expression ]]
命令说明:在单方括号的基础上,增加了模式匹配
命令注意:并不是所有的shell都支持双方括号
编写test24.sh脚本
#!/bin/bash
# using pattern matching
#
if [[ $USER == z* ]]
then
echo "Hello $USER"
else
echo "Sorry,I do not know you"
fi
12.7 case命令
编写test25.sh脚本
#!/bin/bash
# looking for a possible value
#
if [ $USER = "zc" ]
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 "Do not forget to logout when you're done"
else
echo "Sorry, you are not allowd here"
fi
命令格式:
case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) commands3;;
esac
命令说明:case命令会将指定的变量与不同模式进行比较
编写test26.sh脚本
#!/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 "Do not forget to log off when you're done";;
*)
echo "Sorry, you are not allowed here";;
esac
12.8 小结
结构化命令可以改变shell脚本的正常执行流。最基本的结构化命令是if-then语句。该语句可以根据一个执行一个命令的结果来执行其他命令。本章介绍了if-then、if-then-else、elif、case语句。