美文网首页程序员联盟Linux探索之旅简书收藏--linux
Linux探索之旅 | 第五部分第四课:条件一出,Shell不服

Linux探索之旅 | 第五部分第四课:条件一出,Shell不服

作者: 程序员联盟 | 来源:发表于2017-04-04 00:17 被阅读1901次

作者 谢恩铭 转载请注明出处
公众号「程序员联盟」(微信号:ProgrammerLeague )
原文:http://www.jianshu.com/p/471f8d07542e


《Linux探索之旅》全系列

内容简介


  1. 前言
  2. if : 最简单的条件
  3. 条件测试
  4. case : 测试多个条件
  5. 总结
  6. 第五部分第五课预告

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 个 ( $# 大于或等于 1 )
  2. 第一个参数是否等于 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. 总结


  1. 我们可以用下面的语法来做条件测试:「 if, then, [ [ elif, then, fi ] else, ] fi 」。

  2. 我们可以测试字符串,也可以测试数字,也可以测试文件。例如文件存在吗?文件是否可执行?等等。

  3. 如果需要,我们可以综合好几种测试,用 && (逻辑与),|| (逻辑非)符号。

  4. 感叹号( ! )表示条件「否」,用于反转条件测试。

  5. 当我们对同一个变量做好多测试时,一般用 case 语句比 if 语句更直观。

6. 第五部分第五课预告


今天的课就到这里,一起加油吧!

下一课我们学习:Linux探索之旅 | 第五部分第五课:循环往复,Shell开路


我是 谢恩铭,在巴黎奋斗的软件工程师。
我创建了程序员联盟的 知识星球,欢迎加入。
热爱生活,喜欢游泳,略懂烹饪。
人生格言:「向着标杆直跑」

相关文章

网友评论

  • 50862d60a94f:赞~\(≧▽≦)/~
    程序员联盟:@zhangpeter 谢谢
  • 754c54f0ba62:1 #!/bin/bash
    2
    3 if [ -n $1 ]; then
    4 echo "There is parameter"
    5 else
    6 echo "No parameter"
    7 fi
    这是我写的一个脚本,运行时不管我有没有输入参数都是输出:There is parameter。。。感觉好奇怪啊。。
    754c54f0ba62:@程序员联盟
    1 #!/bin/bash
    2
    3 if [ -n $nameddd ]; then
    4 echo "Yes"
    5 else
    6 echo "No"
    7 fi
    随便测试一个变量,不管有没有给这个变量赋值,都是输出“Yes”。。。
    程序员联盟:@clearbug 应该是把回车当作参数了。
  • a4c46c57874e:凌晨还在写!
    程序员联盟:@简_云 我在法国巴黎,时差6小时

本文标题:Linux探索之旅 | 第五部分第四课:条件一出,Shell不服

本文链接:https://www.haomeiwen.com/subject/cewbottx.html