作者 谢恩铭 转载请注明出处
公众号「程序员联盟」(微信号:ProgrammerLeague )
原文:http://www.jianshu.com/p/471f8d07542e
《Linux探索之旅》全系列
内容简介
- 前言
- if : 最简单的条件
- 条件测试
- case : 测试多个条件
- 总结
- 第五部分第五课预告
1. 前言
上一课 Linux探索之旅 | 第五部分第三课:变量在手,Shell不愁 有不少内容,这一课我们轻松一下,来聊聊条件语句。
有个对联说得好:
「说你行,你就行,不行也行」
「说不行,就不行,行也不行」
「横批:不服不行」
因此「条件一出,Shell 不服不行」。
读者:小编你这是什么逻辑?我们地球人表示不理解... 我看你还是回火星比较好。
小编:为了压韵,也是蛮拼的...
对于所有编程语言,做决定是很重要的。如果程序员不决定程序做什么,那么程序只会一直做同样的事情,就很无趣了。
而条件语句就是用于帮助程序做决定的。在我们的 Shell 脚本中,条件语句可以做以下「抉择」:
如果,变量的值等于 xxx ,
那么,这样做;
否则,那样做。
如果你学过某一门编程语言,例如 C 语言 ( 欢迎学习我的 C语言探索之旅 ),那么对于条件语句的原理应该很熟悉了。
即使你没学过其他编程语言,那也不必担心,跟着我们学完这课,保证你了然于胸。
2. if : 最简单的条件
最常用的条件语句就是 if 条件语句。
if 是英语「如果」的意思。
if 条件语句的基本格式是这样的:
if [ 条件测试 ]
then
做这个
fi
fi 是 if 的反转写法,表示「if 语句结束」。
then 是英语「那么」的意思。
「做这个」只有在「条件测试」为真时,才会被执行。
注意:方括号 [] 中的「条件测试」两边必须要空一格。不能写成 [test],而要写成[ test ]。
唉,Shell 就是这么任性,你不服都不行!
当然了,if 语句的基本写法还有一种,那就是把 then 写在 if [ 条件测试 ] 后面,如下:
if [ 条件测试 ]; then
做这个
fi
用这种写法时,在 if 条件判断和 then 之间要加一个分号。
我们写 Shell 程序时,需要把「条件测试」换成我们真实要测试的条件,一般来说都是测试变量的值。
我们可以通过例子来学习,首先创建一个叫做 condition.sh 的文件( condition 是英语「条件」的意思)。
vim condition.sh
然后在里面输入以下内容:
#!/bin/bash
name="Enming"
if [ $name = "Enming" ]
then
echo "Hello $name !"
fi
在 Shell 语言中,「等于」是用一个等号( = )来表示的,这和大多数主流编程语言不同。C语言中「等于」是用两个等号( == )来表示的。但 Shell 中用两个等号来表示「等于」的判断也是可以的。
上例中,因为变量 name 的值等于 "Enming",因此会输出 「Hello Enming !」
当然了,我们也可以测试两个变量,例如:
#!/bin/bash
name1="Enming"
name2="Oscar"
if [ $name1 = $name2 ]
then
echo "You two have the same name !"
fi
「 You two have the same name 」是英语「你们俩有相同的名字」的意思。
运行上面的程序,可以看到什么也没有显示,因为「 Enming 」和「 Oscar 」这两个字符串不相同。
else : 否则
既然有「如果」的条件判断,那么也会存在条件不成立的时候,就好比上面那个程序中,「 Enming 」和「 Oscar 」这两个字符串不相同的情况。
我们已经知道表示「如果」的关键字是 if,那么表示「否则」的关键字应该就是 「else」咯?
没错。因为 else 就是英语「否则」的意思。
所以学好英语对于编程帮助极大:对于程序员, 为什么英语比数学更重要? 如何学习 。
因此,if 和 else 两者配合的逻辑是这样的:
if [ 条件测试 ]
then
做这个
else
做那个
fi
也就是:如果「条件测试」为真,那么「做这个」被执行;否则,「做那个」被执行。
我们来看一个例子:
#!/bin/bash
name1="Enming"
name2="Oscar"
if [ $name1 = $name2 ]
then
echo "You two have the same name !"
else
echo "You two have different name !"
fi
运行:
「 You two have different name 」是英语「你们有不同的名字」的意思。
elif : 否则,如果
一般来说 if 和 else 已经能满足我们的大部分条件判断需要了,但有些时候,存在好几种情况。
光是 if 和 else 表示的两种对立的情况已经不足以满意要求了,因此我们再来学习一个关键字:elif 。
elif 是 「 else if 」的缩写,表示「否则 - 如果」。
if, elif 和 else 三者配合的逻辑是这样的:
if [ 条件测试 1 ]
then
做 1 的事情
elif [ 条件测试 2 ]
then
做 2 的事情
elif [ 条件测试 3 ]
then
做 3 的事情
else
做其他事情
fi
我们来看一个例子:
#!/bin/bash
if [ $1 = "Matthew" ]
then
echo "Hello Matthew !"
elif [ $1 = "Mark" ]
then
echo "Hello Mark !"
elif [ $1 = "Luke" ]
then
echo "Hello Luke !"
elif [ $1 = "John" ]
then
echo "Hello John !"
else
echo "Sorry, I do not know you."
fi
「 Sorry, I do not know you 」是英语「对不起,我不认识你」的意思。
运行:
我们可以写任意多个 elif 语句,但是 if 语句必须要有且只能有一个,else 语句最多只能有一个。
我们可以有单独由 if 语句组成的条件语句,也可以有「 if ... else ... 」组成的条件语句,也可以有「 if ... elif ... else... 」组成的条件语句,也可以有「 if ... elif ... 」组成的语句。
3. 条件测试
现在我们来看看我们都能做哪些「条件测试」。
之前的例子,我们只比较了字符串,但其实我们远可以做比这更复杂的条件测试。
不同的测试类型
在 bash 中我们可以做三种测试:
- 测试字符串
- 测试数字
- 测试文件
我们通过例子一一来学习。
测试字符串
我们之前的课程已经说过:在 Shell 中,所有的变量都是字符串。
因此,要做字符串的测试非常简单。记住以下表格:
条件 | 意义 |
---|---|
$string1 = $string2 | 两个字符串是否相等。Shell 大小写敏感,因此 A 和 a 是不一样的。 |
$string1 != $string2 | 两个字符串是否不同。 |
-z $string | 字符串 string 是否为空。z是 zero 的首字母,是英语「零」的意思。 |
-n $string | 字符串 string 是否不为空。n 是英语 not 的首字母,是英语「不」的意思。 |
例如:
#!/bin/bash
if [ -z $1 ]
then
echo "No parameter"
else
echo "There is parameter"
fi
「 No parameter 」是英语「没有参数」的意思。
「 There is parameter 」是英语「有参数」的意思。
测试数字
尽管 Shell 把所有变量都看成字符串,但是我们还是可以做数字的条件测试。记住以下表格:
条件 | 意义 |
---|---|
$num1 -eq $num2 | 两个数字是否相等。和判断字符串所用的符号( = )不一样。eq 是 equal 的缩写,是英语「等于」的意思。 |
$num1 -ne $num2 | 两个数字是否不同。ne 是 not equal 的缩写,是英语「不等于」的意思。 |
$num1 -lt $num2 | 数字 num1 是否小于 num2。lt 是 lower than 的缩写,是英语「小于」的意思。 |
$num1 -le $num2 | 数字 num1 是否小于或等于 num2。le 是 lower or equal 的缩写,是英语「小于或等于」的意思。 |
$num1 -gt $num2 | 数字 num1 是否大于 num2。gt 是 greater than 的缩写,是英语「大于」的意思。 |
$num1 -ge $num2 | 数字 num1 是否大于或等于 num2。ge 是 greater or equal 的缩写,是英语「大于或等于」的意思。 |
看一个例子:
#!/bin/bash
if [ $1 -ge 10 ]
then
echo "You have entered 10 or more"
else
echo "You have entered less than 10"
fi
「 You have entered 10 or more 」是英语「你的输入等于 10 或比 10 更大」的意思。
「 You have entered less than 10 」是英语「你的输入小于 10」的意思。
测试文件
相比于主流编程语言,Shell 的一大优势就是可以非常方便地测试文件:文件存在吗?我们可以写入文件吗?这个文件比那个文件修改时间更早还是更晚?等等。
下表非常丰富:
条件 | 意义 |
---|---|
-e $file | 文件是否存在。e 是 exist 的首字母,表示「存在」。 |
-d $file | 文件是否是一个目录。因为 Linux 中所有都是文件,目录也是文件的一种。d 是 directory 的首字母,表示「目录」。 |
-f $file | 文件是否是一个文件。f 是 file 的首字母,表示「文件」。 |
-L $file | 文件是否是一个符号链接文件。L 是 link 的首字母,表示「链接」。 |
-r $file | 文件是否可读。r 是 readable 的首字母,表示「可读的」。 |
-w $file | 文件是否可写。w 是 writable 的首字母,表示「可写的」。 |
-x $file | 文件是否可执行。x 是 executable 的首字母,表示「可执行的」。 |
$file1 -nt $file2 | 文件 file1 是否比 file2 更新。nt 是 newer than 的缩写,表示「更新的」。 |
$file1 -ot $file2 | 文件 file1 是否比 file2 更旧。ot 是 older than 的缩写,表示「更旧的」。 |
来看一个例子:
#!/bin/bash
read -p 'Enter a directory : ' file
if [ -d $file ]
then
echo "$file is a directory"
else
echo "$file is not a directory"
fi
运行:
一次测试多个条件
在一个条件测试中,我们可以同时测试多个条件。需要用到两种符号:
符号 | 意义 |
---|---|
&& | 两个&。表示「逻辑与」。此符号两端的条件必须全为真,整个条件测试才为真;只要有一个不为真,整个条件测试为假。 |
II | 两个竖线。表示「逻辑或」。此符号两端的条件只要有一个为真,整个条件测试就为真;只有两个都为假,整个条件测试才为假。 |
来看一个例子:
#!/bin/bash
if [ $# -ge 1 ] && [ $1 = 'love' ]
then
echo "Great !"
echo "You know the password"
else
echo "You do not know the password"
fi
「 Great ! You know the password 」是英语「好极了!你知道密码」的意思。
「 You do not know the password 」是英语「你不知道密码」的意思。
上面的测试检验了两个条件:
- 参数是否至少有 1 个 ( $# 大于或等于 1 )
- 第一个参数是否等于 love( $1 是否等于 love )
在做多个条件的判断时,是按照从左到右的顺序判断的,如果前一个条件已经足以决定整个条件测试的真或假,那么后面的条件就不会被判断。
例如 [ 2 -ge 1 ] || [ 3 -gt 2 ] 中,2 是大于等于 1 的,因此,「 2 -ge 1 」已经为真,整个条件语句肯定为真,「 3 -gt 2 」就不需要被判断了。
而 [ 2 -ge 4 ] && [ 5 -gt 2 ] 中,2 是小于 4 的,因此,「 2 -ge 4 」已经为假,整个条件语句肯定为假,「 5 -gt 2 」就不需要被判断了。
反转测试
我们可以用「否定」来反转测试条件,要用到感叹号( ! )。
来看一个例子:
#!/bin/bash
read -p 'Enter a file : ' file
if [ ! -e $file ]
then
echo "$file does not exist"
else
echo "$file exists"
fi
条件测试中我们写了 「 ! -e $file 」,表示「如果文件 file 不存在」。
exist 是英语「存在」的意思。
运行:
4. case : 测试多个条件
之前,我们写过一个例子,用来演示多个条件测试的情况:
#!/bin/bash
if [ $1 = "Matthew" ]
then
echo "Hello Matthew !"
elif [ $1 = "Mark" ]
then
echo "Hello Mark !"
elif [ $1 = "Luke" ]
then
echo "Hello Luke !"
elif [ $1 = "John" ]
then
echo "Hello John !"
else
echo "Sorry, I do not know you."
fi
这个程序当然没有错,但是它只对同一个变量做测试(我们输入的参数 1),却用了这么多 elif... then... 未免略显繁琐,也不是很好理解。
像这样的情况,我们可以用 case 语句来实现。
case 是英语「情况」的意思。
我们上面的程序可以改写成这样:
#!/bin/bash
case $1 in
"Matthew")
echo "Hello Matthew !"
;;
"Mark")
echo "Hello Mark !"
;;
"Luke")
echo "Hello Luke !"
;;
"John")
echo "Hello John !"
;;
*)
echo "Sorry, I do not know you."
;;
esac
运行之后与之前的程序效果一样。
来分析一下上面的程序。因为有很多新的内容:
-
case $1 in :$1 表示我们要测试的变量是输入的第一个参数。in 是英语「在...之中」的意思。
-
"Matthew") :测试其中一个 case,也就是 $1 是否等于 "Matthew"。当然,我们也可以用星号来做通配符来匹配多个字符,例如 "M*") 可以匹配所有以 M 开头的字符串。
-
;; :类似于主流编程语言中的 「 break; 」,表示结束 case 的读取,程序跳转到 esac 后面执行。
-
*) :相当于 if 条件语句的 else,表示「否则」,就是「假如不等于上面任何一种情况」。
-
esac :是 case 的反写,表示 case 语句的结束。
其实 case 语句就相当于主流编程语言中的 switch 语句。
我们也可以在case 语句的匹配项中做「或」的匹配,但是不是用两个竖线(逻辑或)了,而是用一个竖线。
来看一个例子:
#!/bin/bash
case $1 in
"dog" | "cat" | "pig")
echo "It is a mammal"
;;
"pigeon" | "swallow")
echo "It is a bird"
;;
*)
echo "I do not know what it is"
;;
esac
「 It is a mammal 」是英语「这是一只哺乳动物」的意思。
「 It is a bird 」是英语「这是一只鸟」的意思。
「 I do not know what it is 」是英语「我不知道这是什么」的意思。
运行:
5. 总结
-
我们可以用下面的语法来做条件测试:「 if, then, [ [ elif, then, fi ] else, ] fi 」。
-
我们可以测试字符串,也可以测试数字,也可以测试文件。例如文件存在吗?文件是否可执行?等等。
-
如果需要,我们可以综合好几种测试,用 && (逻辑与),|| (逻辑非)符号。
-
感叹号( ! )表示条件「否」,用于反转条件测试。
-
当我们对同一个变量做好多测试时,一般用 case 语句比 if 语句更直观。
6. 第五部分第五课预告
今天的课就到这里,一起加油吧!
下一课我们学习:Linux探索之旅 | 第五部分第五课:循环往复,Shell开路
我是 谢恩铭,在巴黎奋斗的软件工程师。
我创建了程序员联盟的 知识星球,欢迎加入。
热爱生活,喜欢游泳,略懂烹饪。
人生格言:「向着标杆直跑」
网友评论
2
3 if [ -n $1 ]; then
4 echo "There is parameter"
5 else
6 echo "No parameter"
7 fi
这是我写的一个脚本,运行时不管我有没有输入参数都是输出:There is parameter。。。感觉好奇怪啊。。
1 #!/bin/bash
2
3 if [ -n $nameddd ]; then
4 echo "Yes"
5 else
6 echo "No"
7 fi
随便测试一个变量,不管有没有给这个变量赋值,都是输出“Yes”。。。