本章内容
- 使用if-then语句
- if-then-else语句
- 嵌套if
- test命令
- 复合条件测试
- if-then的高级特性
- case命令
- 管理用户账户
在第10章中给出的那些shell脚本中,shell按照出现的次序来处理shell脚本中的每个单独命令。对于顺序操作来谙已经足够了,如果你只想所有的命令都能按正确的顺序执行。然而,并非所有程序都如此操作。
许多程序要求在shell脚本中的命令间有一些逻辑流控制。这意味着shell在某些环境下执行特定的命令,但在其他某些环境下执行另外一些命令。有一类命令会基于变量或其他命令的结果等条件使用脚本跳过或循环执行命令。这样的命令通常称为结构化命令(structured command)。
结构化命令允许你改变程序执行的顺序,在某些条件下执行一些命令而在其他条件下跳过另一些命令。在bash shell中有不少结构化命令,我们会逐个研究它们。在本章,我们来看一下if-then语句。
11.1 使用if-then语句
结构化命令中,最基本的类型就是if-then语句。if-then语句有如下格式:
if command
then
command
fi
如果你在用其他编程语言的if-then语句,这种形式可能会让你的点困惑。在其他编程语言中,if语句之后的对象是一个等式来测试是TRUE还是FALSE值。bash shell的if语句并非如此工作。
bash shell的if语句会运行if行定义的那个命令。如果该命令的退出状态码(参见第10章)是0(该命令成功运行),位于then部分的命令就会被执行。如果该命令的退出状态码是其他什么值,那then部分的命令就不会被执行。bash shell会继续执行脚本中的下一下命令。
这里有个简单的例子来解释这个概念:
[root@localhost ch11]# cat test1
#!/bin/bash
#testing the if statement
if date
then
echo "it wroked"
fi
这个脚本在if行采用了date命令。如果命令成功结束了,echo语句就会显示该文本字符串。
当你在命令行运行该脚本时,你会得到如下结果:
[root@localhost ch11]# ./test1
2018年 06月 13日 星期三 23:08:46 CST
it wroked
shell执行了if行的date命令。由于退出码是0,它就又执行了then部分的echo语句。
下面是另外一个例子:
[root@localhost ch11]# cat test2
#!/bin/bash
#testing a bad command
if esdfg
then
echo "it did not work"
fi
echo "we are outside of the if statement"
[root@localhost ch11]# ./test2
./test2:行3: esdfg: 未找到命令
we are outside of the if statement
在这个例子中,我们在if语句行故意放了一个不能工作的命令。由于这个命令没法工作,它会输出一个非零的退出状态码,bash shell会跳过then部分的echo语句,还要注意。运行if语句名的那个命令所生成的错误消息依然会在脚本的输出中。有时你不想这种情况发生。第14章将会讨论如何避免这种情况。
在then部分,你可以用多个命令。你可以你脚本中其他地方一样列出多条命令。 bash shell会将这部分命令当成一个块,在if语句行的那个命令返回退出状态码0时执行这块命令,在该命令返回非零退出状态码时跳过这块命令:
[root@localhost ch11]# cat test3
#!/bin/bash
#testing multiple commands in the then section
testuser=rich
if grep $testuser /etc/passwd
then
echo The bash files for user $testuser are:
ls -a /home/$testuser/.b*
fi
if语句行使了grep命令在/etc/passwd文件中查找某个特定用户名是否在当前系统上使用。如果有用户使用了那个登录名,脚本会显示一些文本并列出该用户(HOME)目录的bash文件:
[root@localhost ch11]# ./test3
rich:x:1001:1001::/home/rich:/bin/bash
The bash files for user rich are:
/home/rich/.bash_logout /home/rich/.bash_profile /home/rich/.bashrc
但是,如果你将testuser变量设置成一个系统上不存在的用户,则什么都不会显示:
[root@localhost ch11]# ./test3
[root@localhost ch11]#
看起来也没什么新鲜的。可能我们在这里显示一些消息说明这个用户在系统中未找到会稍微友好一些。是的,我们可以做到,用if-then语句的另外一个特性。
说明 你可能会在一些脚本中看到if-then 语句的另一种格式:
if command; then
commands
fi
在要执行的命令结尾加个分号,你就能在同一行使用then语句了,这样看起来就更像其他编程语言中的if-then语句是如何处理的了。
11.2 if-then-else语句
在if-then语句中,不管命令是否成功执行,你都只有一种选择。如果命令返回一个非零退出状态码,bash shell仅会继续执行脚本中的下一条命令。在这种情况下,如果能够执行另一组命令就好了。这正是if-then-else语句的作用。
if-then-else语句在语句中提供了另外一组命令:
if command
then
command
else
command
fi
当if语句中的命令返回退出状态码0时,then部分中的命令会被执行,跟普通的if-then语句一样。当if语句中的命令返回非零退出状态码时,bash shell会执行else部分中的命令。
现在你可以参考如下修改测试脚本:
[root@localhost ch11]# cat test4
#!/bin/bash
#testing multiple commands in the then section
testuser=rich123
if grep $testuser /etc/passwd
then
echo The bash files for user $testuser are:
ls -a /home/$testuser/.b*
else
echo "The user name $testuser does not exist on thsi system"
fi
这样就更友好了。跟then部分一样,else 部分可以包含多条命令。fi语句说明else部分结束了。
11.3 嵌套if
有时,你需要检查脚本代码中的多种条件。不用写多个分立的if-then语句,你可以用else部分的替代版本,称作elif。
elif会通过另一个if-then语句来延续else部分:
if command
then
command
elif command2
then
more command
fi
elif语句行提供了另一个要测试的命令,类似于原始的if语句。如果elif后命令的退出状态码是0,则bash会执行第二个then语句部分的命令。
你可以继续将多个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 4
fi
每块命令都会根据哪个命令会返回退出状态码0来执行。记住,bash shell会依次执行if语句,只有第一个返回退出状态码0的语句的then部分会被执行。在11.7节,你将了解如何用case命令而不用嵌套多个if-then语句。
11.4 test 命令
到目前为止,你所了解的if语句的命令都是普通shell命令。佝可能想问,if-then语句是否能测试跟命令的退出状态码无关的条件。
答案是不能。但是,在bash shell中有个好用的工具可以帮你通过if-then语句测试其他条件。
test命令提供了在if-then语句中测试不同条件的途径。如果test命令中列出的条件成立,test命令就会退出并返回退出状态码0,这样if-then语句就与其他编程语言的if-then语句以类似方式工作了。如果条件不成立,test命令就会退出并返回退出状态码1,这样if-then 语句就会会失效。
test 命令的格式非常简单:
test condition
condition是test 命令要测试的一系列参数和值。当用在if-then 语句中时,test命令看起来是这样的:
if test condition
then
command
fi
bash shell提供了另一种在if-then语句中声明test命令的方法:
if [ condition ]
then
commands
fi
方括号定义了test命令中用到的条件。注意,你必须在左括号右侧和右括号左侧各加一个空格,否则会报错。
test命令可以判断3类条件:
数值比较;
字符串比较;
文件比较。
后续章节将会介绍如何在if-then语句中使用这3类条件测试。
11.4.1 数值比较
使用test命令最常见的情形是对两个数值进行比较。表11-1列出了测试两个值时可用的条件参数。
表11-1 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 |
数值条件测试可以用在数字和变量上。这里有个例子:
[root@localhost ch11]# cat test5
#!/bin/bash
#using numeric test comparisons
val1=10
val2=11
if [ $val1 -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 diffrernt"
fi
第一个条件测试:
if [ $val1 -gt 5 ]
会测试变量val1 的值是否大于5。第二个条件测试:
if [ $val1 -eq $val2 ]
会测试变量val1的值是否和变量val2的值相等。运行脚本并观察结果:
[root@localhost ch11]# ./test5
The test value 10 is greater than 5
The values are diffrernt
两个数值条件测试都跟预期的一样执行了。
但是测试数值条件也有个限制。看下面的脚本:
[root@localhost ch11]# cat test6
#!/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
[root@localhost ch11]# ./test6
The test value is 3.3333
./test6: 第 5 行:[: 3.3333: 期待整数表达式
这个例子使用了bash计算器生成一个浮点值并存储在变量val1中。下一步,它使用了test命令来判断这个值。显然这里出错了。
在第10章中,你已经了解了如何在bash shell中处理浮点数值;在脚本中仍然有一个问题。test命令无法处理val1变量中储存的浮点值。
记住,bash shell能处理的数仅有整数。当你使用bash计算器时,你可以让shell将浮点值作为字符串存储进一个变量。如果你只是要通过echo语句来显示这个结果,那它可以很好地工作;但它无法在基于数字的函数中工作,例如我们的数值测试条件。尾行恰好说明了你不能在test命令中使用浮点值。
11.4.2 字符串比较
test命令还允许比较字符串值。比较对字符串比较烦琐,你马上就会看到。表11-2列出了可用来比较两个字符串值的函数。
表11-2 test命令的字符串比较功能
比较 | 描述 |
str1 = str2 | 检查str1是否和str2相同 |
str1 != str2 | 检查str1是否和str2不同 |
str1 < str2 | 检查str1是否和str2小 |
str1 ? str2 | 检查str1是否和str2大 |
-n str1 | 检查str1的长度是否非0 |
-z str1 | 检查str1的长度是否为0 |
1.字符串相等性
2.字符串顺序
3.字符串大小
14.4.3
最后一类测试比较可能是shell编程中最强大的也是最经常用到的比较。test命令允许你测试Linux文件系统上文件和目录的状态。表11-3列出了这此比较。
比较 | 描述 |
-d file | 检查file是否存在并是一个目录 |
-e file | 检查fike是否在在 |
-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测试会检查指定的文件名是否在系统上以目录形式存在。当写文件到某个目录之前,或者是将文件放置到某个目录位置之前时,这会非常有用:
[root@localhost ch11]# cat test11
#!/bin/bash
#look before you leap
if [ -d $HOME ]
then
echo "Your HOME directory exists"
cd $HOME
ls -a
else
echo "THere is a problem with your HOME directory"
fi
[root@localhost ch11]# ./test11
Your HOME directory exists
. anaconda-ks.cfg .bash_logout .bashrc installed_software sysstat-11.7.4 .tcshrc
.. .bash_history .bash_profile .cshrc linux_shell sysstat-11.7.4.tar.gz .viminfo
示例代码中使用了-d测试条件来检查用户的$HOME目录是否存在。如果它存在的话,它将继续使用cd命令来切到$HOME目录并进行目录列表。
2.检查对象是否存在
[root@localhost ch11]# cat test12
#!/bin/bash
# checking if a directory exists
if [ -d $HOME ]
then
echo "OK on the directory,now to check the file"
#checking if a file exists
if [ -e $HOME/testing ]
then
#theck file exists,append data to it
echo "Appending data to existing file"
date >> $HOME/testing
else
#the file does not exist,create a new file
echo "Creating new file"
date > $HOME/testing
fi
else
echo "Sorry,you do not have a HOME directory"
fi
[root@localhost ch11]# ./test12
OK on the directory,now to check the file
Appending data to existing file
第一个检查用-d比较来判断用户是否有$HOME目录。如果有,下一个--e比较会检查并判断testing文件存在于$HOME目录中。如果文件不存在,shell脚本会用单个大于号(输出重定向符号)来用date命令的输出创建一个新文件。你第二次运行这个shell脚本时,它会使用双大于号,这样它就能将date的输出追加到已经存在的文件后面。
3.检查文件
-e比较适用于文件和目录。要确定指定的对象是个文件,你必须用-f比较:
[root@localhost ch11]# cat test13
#!/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 is a file!"
else
echo "No,it is not a file!"
if [ -f $HOME/.bash_history ]
then
echo "But this is a file!"
fi
fi
else
echo "Sory,the object does not exist"
fi
[root@localhost ch11]# ./test13
The object exists,is it a file?
No,it is not a file!
But this is a file!
这一小段脚本作了很多检查。首先,它用-e 比较测试 $HOME是否存在。如果存在,继续用-f来测试它是不是一个文件。如果它不是文件(当然不会是文件),我们用-f比较来测试$HOME/.bash_history是不是一个文件(当然,是个文件)。
4.检查是否可读
在尝试从文件中读取数据之前,最好先测试一下是否能读文件。你可以通过-r比较测试:
[root@localhost ch11]# cat test14
#!/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 $file does not exist"
fi
/etc/shadow文件含有系统用户加密后的密码,所以它对系统上的普通用户是不可读的。-r比较判断出我没有这个文件的读权限,所以test命令失败了,而且bash shell执行了if-then语句的else部分。
5.检查空文件
你应该用-s比较来检查文件是否为空,尤其是在你要删除文件时。当-s比较成功时要特别小心,它说明文件中有数据:
[root@localhost ch11]# cat test15
#!/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
[root@localhost ch11]# ./test15
The t15test exists and is empty
The t15test file has data in it
touch 命令创建了这个文件但不会写入任何数据。在我们使用date命令并将其输出重定向到文件中后,-s比较说明文件中有数据。
6.检查是否可写
-w比较会判断你是否对文件有可写权限:
[jingpan@localhost ch11]$ cat test16
#!/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 ]
then
echo "The program ran at:$now" > $logfile
echo "The first attempt succeptded"
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 succeptded"
else
echo "The second attempt failed"
fi
[jingpan@localhost ch11]$ ./test16
The first attempt failed
The second attempt succeptded
[jingpan@localhost ch11]$ cat $HOME/t16test
The program ran at:20180614-1101
这个脚本内容很多。首先,它在你的$HOME目录定义了一个日志文件,将文件名存进变量logfile中,创建文件并通过chmod命令移除该用户对文件的写权限。下一步,它创建了变量now并通过date命令保存了一个时间戳。在这之后,它会检查你是否对新日志文件有写权限(你刚刚移除了写权限)。由于现在你没有了写权限,你应该会看到那条未成功消息。
之后,脚本双通过chmod命令重新赋予该用户写权限,并再次尝试写文件。这次写入成功了。
7.检查是否可执行
-x比较是一个简单的判断你对某个特定文件是滞有执行权限的方法。虽然可以大多数命令用不到它,但如果你要在shell脚本中运行大量脚本,它可能很方便:
[jingpan@localhost ~]$ cat test17
#!/bin/bash
# testing file exectiion
if [ -x test16 ]
then
echo "You can run the script:"
./test16
else
echo "Sory ,you are unable to execute the script"
fi
[jingpan@localhost ~]$ ./test17
You can run the script:
The first attempt failed
The second attempt succeptded
[jingpan@localhost ~]$ chmod u-x test16
[jingpan@localhost ~]$ ./test17
Sory ,you are unable to execute the script
这段示例shell脚本用-x比较来测试是否有权限执行test16脚本。如果有权限,它会运行这个脚本(注意,即使是在shell脚本中,你必须用正确的路径来执行不在你的$PATH路径中的脚本)。在首次成功运行test16脚本后,更改文件的权限并再试。这次,-x比较失败了,因为你没有test16脚本的执行权限。
8. 检查所属关系
-O比较允许你测试你是否是文件的属主:
[jingpan@localhost ch11]$ cat test18
#!/bin/bash
#check 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
[jingpan@localhost ch11]$ ./test18
Sorry ,you are not the owner of the /etc/passwd file
[jingpan@localhost ch11]$ su
密码:
[root@localhost ch11]# ./test18
You are the Owner of the /etc/passwd file
这段脚本用-O比较来测试运行该脚本的用户是否是/etc/passwd文件的属主。第一次,这个脚本运行在普通用户账户下,所以测试失败了。第二次,我们用su命令切换到root用户,测试通过了。
9检查默认属组关系
-G比较会检查文件的默认组,如果它匹配了用户的默认组,那就通过了。由于-G比较只会检查默认给而非用户所属的所有组,这会叫人有点困惑。这里有个例子:
[jingpan@localhost ch11]$ cat test19
#!/bin/bash
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
[jingpan@localhost ch11]$ ls -l $HOME/testing
-rw-rw-r--. 1 jingpan jingpan 0 6月 14 12:35 /home/jingpan/testing
[jingpan@localhost ch11]$ ./test19
You are in the same group as the file
[jingpan@localhost ch11]$ chgrp sharing $HOME/testing
[jingpan@localhost ch11]$ ./test19
The file is not owned by your group
第一次运行脚本旱,$HOME/testing文件是在jingpan组的,所以-G比较通过了。下一次,组被改成了sharing组,用户也是其中的一员,但-G比较失败了,因为它只比较默认组,不会去比较其他额外的组。
10.检查文件日期
最后一组方法用来进行两个文件创建日期相关的比较。这在编写安装软件的脚本时非常有用。有时你不会想安装一个比系统上已安装文件还要早的文件。
-nt 比较会判定某个文件是否比另一个文件更新。如果文件更新,那它会有一个比较近的文件创建日期。-ot比较会判定某个文件是否比另一个文件更老。如果文件更老,它会有一个更早的创建日期:
[jingpan@localhost ch11]$ cat test20
#!/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 [ ./test18 -ot ./test19 ]
then
echo "The test18 file is older than test19 file"
fi
[jingpan@localhost ch11]$ ./test20
The test19 file is newer than test18
The test18 file is older than test19 file
[jingpan@localhost ch11]$ ls -l test18 test19
-rwxrw-r--. 1 jingpan jingpan 182 6月 14 12:26 test18
-rwxrw-r--. 1 jingpan jingpan 140 6月 14 12:40 test19
比较中用到的文件路径是相对于你运行该脚本的目录来说的。如果你需要检查的文件是可以被移来称去,这可能会造成一些问题。另一个问题是这些比较中没有哪个会先检查文件是否存在。试试这个测试:
[jingpan@localhost ch11]$ cat test21
#!/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
[jingpan@localhost ch11]$ ./test21
The badfile2 file is newer than badfile1
这个小例子演示了如果文件不存在,-nt比较会返回一个无效的条件。在你尝试在-nt或-ot比较中使用文件之前,必须确认文件存在。
11.5 复合条件测试
if-then 语句允许你使用布尔逻辑来组合测试。有两种布尔运算符可用:
[condition1] && [condition2];
[condition1] || [condition2]。
第一个布尔运算使用AND布尔运算符来组合两个条件。要让then部分的命令执行,两个条件都必须满足。
第二个布尔运算符用OR布尔运算来组合两个条件。如果任何一个条件最后都能得到一个真值,then部分的命令就会执行。
[jingpan@localhost ch11]$ cat test22
#!/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 cannot write to the file"
fi
[jingpan@localhost ch11]$ ./test22
I cannot write to the file
[jingpan@localhost ch11]$ touch $HOME/testing
[jingpan@localhost ch11]$ ./test22
The file exists and you can write to it
使用AND布尔运算符时,两个比较都必须满足。第一个比较会检查用户的$HOME目录是否存在。第二个比较会检查在用户的$HOME目录是否有个叫testing文件,以及用户是否有该文件的写权限。如果两个比较中的任意一个失败了,if语句就会失败,shell就会执行else部分的命令。如果两个比较都通过了,if语句就通过了,shell会执行then部分的命令。
11.6 if-then的高级特性
bash shell有两荐较新的扩展,提供了可在if-then语句中使用的高级特性:
用于数学表达式的双尖括号:
用于高级字符串处理功能的双方括号。
后面几节将会进一步描述这些特性中的每一项。
116.1 使用双尖括号
双尖括号命令允许你将高级数学表达式放入比较中。test命令只允许在比较中进行简单的“算术操作”。双尖括号命令提供了更多的为用过其他编程语言的程序所熟悉的数学符号。双尖括号命令的格式如下:
(( expression))
术语expression可以是任意的数学赋值或比较表达式。除了test命令使用的标准数学运算符,表11-4列出了双尖括号命令中会用到的其他运算符。
表11-4 双尖括号命令符号
符号 | 描述 |
vall++ | 后增 |
val-- | 后减 |
++val | 先增 |
--val | 先减 |
! | 逻辑求反 |
- | 位求反 |
** | 幂运算 |
<< | 左位移 |
>> | 右位移 |
& | 位布尔和 |
| | 位布尔或 |
&& | 逻辑和 |
|| | 逻辑或 |
你可以在if语句中用双尖括号命令,也可以在脚本中的普通命令里使用赋值:
[jingpan@localhost ch11]$ cat test23
#!/bin/bash
#using double parenthesis
val1=10
if(( $val1 ** 2 > 90 ))
then
(( val2 = $val1 ** 2 ))
echo "The square of $val1 is $val2"
fi
[jingpan@localhost ch11]$ ./test23
The square of 10 is 100
注意,你不需要将双尖括号中表达式的大于号转义。这是双尖括号命令提供的另一个高级特性。
11.6.2 使用双方括号
双方括号提供了针对字符串比较的高级特性。双方括号命令的格式如下"
[[ expression ]]
双方括号里的expression使用了test命令中采用的标准字符串进行比较。但它提供了test命令未提供的另一个特性--模式匹配(pattern matching)。
在模式匹配中,你可以定义一个正则表达式(将在第19章中详细讨论)来匹配字符串值:
[jingpan@localhost ch11]$ cat test24
#!/bin/bash
#using pattern matching
if [[ $USER == j* ]]
then
echo "Hello $USER"
else
echo "Sorry ,I do not know you"
fi
[jingpan@localhost ch11]$ ./test24
Hello jingpan
双方括命令匹配了$USER环境变量来看综是否以字母j开关。如果是的话,比较就会通过,shell会执行then部分的命令。
11.7 case命令
你会经常发现自己在尝试计算一个变量的值或在一组可能的值中寻找特定值。在这种情形下,你最终必须写出很长的if-then-else语句,像这样:
[jingpan@localhost ch11]$ cat test25
#!/bin/bash
#looking for a possibel value
if [ $USER = "jingpan" ]
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.your are not allowed here"
fi
[jingpan@localhost ch11]$ ./test25
welcome jingpan
Please enjoy your visit
elif语句进行if-then检查,为单个比较变量寻找特定值。
你可以使用case命令,而不是写出那么多elif语句来不断检查相同变量值。case命令会检查单个变量列表格式的多个值:
case variable in
pattern 1 | pattern2) commands1::
pattern3) command2::
*) default commands::
esac
case命令会将指定的变量同不同模式进行比较。如果变量和模式是匹配的,那么shell会执行为该模式指定的命令。你可以通过竖线操作符来分割模式,在一行列出多个模式。星号会捕获所有列出的模式都不匹配的值。这里有个将if-then-else程序转换成用case命令的例子:
[jingpan@localhost ch11]$ cat test26
#!/bin/bash
#using the case command
case $USER in
rich | barbara)
echo "Welcom,$USER"
echo "Please enjoy your visit";;
testing)
echo "Special testing account";;
jingpan)
echo "Do not forget to log off when you're done";;
*)
echo "Sorry,you are not allowed here";;
esac
[jingpan@localhost ch11]$ ./test26
Do not forget to log off when you're don
case命令提供了一个更清晰的方法来为变量每个可能的值指定不同的选项。
11.8 小结
结构化命令允许你改变shell脚本的正常执行流。最基本的结构化命令是if-then语句。该语句允许你执行一个命令并根据该命令的输出来执行其他命令。
你也可以扩展if-then语句来在指定命令失败时让bash shell执行另一组命令。仅在测试命令返回非零退出状态码时,if-then-else语句才允许执行命令。
你也可以将if-then-else语句通过elif语句连接起来。elif等同于使用else if语句,会在测试命令失败时提供额外的检查。
在很多脚本中,你可能希望测试一种条件而不是一个命令,比如数值,字符串内容或者文件或目录。test命令为你提供了测试所有这些条件的简单方法。如果条件计算出的是真值情况,test命令会为if-then语句产生退出状态码0。如果条件计算出一个假值病况,test命令会为if-then语句产生一个非零的退出状态码。
方括号是与test命令同义的特殊bash命令。你可以在if-then语句中将测试条件放在方括号中来测试数值、字符串和文件条件。
双尖括号允许你使用额外的操作符来进行高级数学运算,双方括号命令允许你进行高级字符串模式匹配运算。
最后,本章讨论了case命令。它是执行多个if-then-else命令的简便方式。会参照一个值列表来检查单个变量的值。
下一章会继续讨论结构化命令,介绍shell的循环命令。for和while命令允许你创建循环来在给定时间内重复执行一些命令。