Linux学习之第十九、条件判断

这个 if …. then 是最常见的条件判断式了~简单的说,就是当符合某个条件判断的时候, 就予以进行某项工作就是了。这个 if … then 的判断还有多层次的情况!我们分别介绍如下:


单层、简单条件判断式

如果你只有一个判断式要进行,那么我们可以简单的这样看:

if [ 条件判断式 ]; then当条件判断式成立时,可以进行的命令工作内容;fi   <==将 if 反过来写,就成为 fi 啦!结束 if 之意!

至於条件判断式的判断方法,与前一小节的介绍相同啊!较特别的是,如果我有多个条件要判别时, 除了sh06.sh那个案例所写的,也就是『将多个条件写入一个中括号内的情况』之外, 我还可以有多个中括号来隔开喔!而括号与括号之间,则以 && 或 || 来隔开,他们的意义是:

&& 代表 AND ;|| 代表 or ;

所以,在使用中括号的判断式中, && 及 || 就与命令下达的状态不同了。举例来说, sh06.sh 里面的判断式可以这样修改:

[ "$yn" == "Y" -o "$yn" == "y" ]上式可替换为[ "$yn" == "Y" ] || [ "$yn" == "y" ]

之所以这样改,很多人是习惯问题!很多人则是喜欢一个中括号仅有一个判别式的原因。好了, 现在我们来将 sh06.sh 这个脚本修改成为 if … then 的样式来看看:

[root@www scripts]# cp sh06.sh sh06-2.sh  <==用改的比较快![root@www scripts]# vi sh06-2.sh#!/bin/bash# Program:#       This program shows the user's choice# History:# 2005/08/25    VBird   First releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHread -p "Please input (Y/N): " ynif [ "$yn" == "Y" ] || [ "$yn" == "y" ]; thenecho "OK, continue"exit 0fiif [ "$yn" == "N" ] || [ "$yn" == "n" ]; thenecho "Oh, interrupt!"exit 0fiecho "I don't know what your choice is" && exit 0

不过,由这个例子看起来,似乎也没有什么了不起吧? sh06.sh 还比较简单呢~ 但是如果以逻辑概念来看,其实上面的范例中,我们使用了两个条件判断呢!明明仅有一个 $yn 的变量,为何需要进行两次比对呢? 此时,多重条件判断就能够来测试测试罗!


多重、复杂条件判断式

在同一个数据的判断中,如果该数据需要进行多种不同的判断时,应该怎么作?举例来说,上面的sh06.sh脚本中,我们只要进行一次 $yn 的判断就好 (仅进行一次 if ),不想要作多次 if 的判断。 此时你就得要知道底下的语法了:

# 一个条件判断,分成功进行与失败进行 (else)if [ 条件判断式 ]; then当条件判断式成立时,可以进行的命令工作内容;else当条件判断式不成立时,可以进行的命令工作内容;fi

如果考虑更复杂的情况,则可以使用这个语法:

# 多个条件判断 (if ... elif ... elif ... else) 分多种不同情况运行if [ 条件判断式一 ]; then当条件判断式一成立时,可以进行的命令工作内容;elif [ 条件判断式二 ]; then当条件判断式二成立时,可以进行的命令工作内容;else当条件判断式一与二均不成立时,可以进行的命令工作内容;fi

你得要注意的是, elif 也是个判断式,因此出现 elif 后面都要接 then 来处理!但是 else 已经是最后的没有成立的结果了, 所以 else 后面并没有 then 喔!好!我们来将 sh06-2.sh 改写成这样:

[root@www scripts]# cp sh06-2.sh sh06-3.sh[root@www scripts]# vi sh06-3.sh#!/bin/bash# Program:#       This program shows the user's choice# History:# 2005/08/25    VBird   First releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHread -p "Please input (Y/N): " ynif [ "$yn" == "Y" ] || [ "$yn" == "y" ]; thenecho "OK, continue"elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; thenecho "Oh, interrupt!"elseecho "I don't know what your choice is"fi

是否程序变得很简单,而且依序判断,可以避免掉重复判断的状况,这样真的很容易设计程序的啦! ^_^! 好了,让我们再来进行另外一个案例的设计。一般来说,如果你不希望使用者由键盘输入额外的数据时, 可以使用上一节提到的参数功能 ($1)!让使用者在下达命令时就将参数带进去! 现在我们想让使用者输入『 hello 』这个关键字时,利用参数的方法可以这样依序设计:

    判断 $1 是否为 hello,如果是的话,就显示 "Hello, how are you ?";如果没有加任何参数,就提示使用者必须要使用的参数下达法;而如果加入的参数不是 hello ,就提醒使用者仅能使用 hello 为参数。

整个程序的撰写可以是这样的:

[root@www scripts]# vi sh09.sh#!/bin/bash# Program:#Check $1 is equal to "hello"# History:# 2005/08/28VBirdFirst releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHif [ "$1" == "hello" ]; thenecho "Hello, how are you ?"elif [ "$1" == "" ]; thenecho "You MUST input parameters, ex> {$0 someword}"elseecho "The only parameter is 'hello', ex> {$0 hello}"fi

然后你可以运行这支程序,分别在 $1 的位置输入 hello, 没有输入与随意输入, 就可以看到不同的输出罗~是否还觉得挺简单的啊! ^_^。事实上, 学到这里,也真的很厉害了~好了,底下我们继续来玩一些比较大一点的计画罗~

我们在第十一章已经学会了grep这个好用的玩意儿,那么多学一个叫做 netstat 的命令,这个命令可以查询到目前主机有开启的网络服务端口 (service ports), 相关的功能我们会在服务器架设篇继续介绍,这里你只要知道,我可以利用『netstat -tuln』来取得目前主机有启动的服务, 而且取得的资讯有点像这样:

[root@www ~]# netstat -tulnActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address     Foreign Address   Statetcp        0      0 0.0.0.0:111       0.0.0.0:*         LISTENtcp        0      0 127.0.0.1:631     0.0.0.0:*         LISTENtcp        0      0 127.0.0.1:25      0.0.0.0:*         LISTENtcp        0      0 :::22             :::*              LISTENudp        0      0 0.0.0.0:111       0.0.0.0:*udp        0      0 0.0.0.0:631       0.0.0.0:*#封包格式           本地IP:端口       远程IP:端口       是否监听

上面的重点是『Local Address (本地主机的IP与端口对应)』那个栏位,他代表的是本机所启动的网络服务! IP的部分说明的是该服务位於那个介面上,若为 127.0.0.1 则是仅针对本机开放,若是 0.0.0.0 或 ::: 则代表对整个 Internet 开放 (更多资讯请参考服务器架设篇的介绍)。 每个端口 (port) 都有其特定的网络服务,几个常见的 port 与相关网络服务的关系是:

80: WWW22: ssh21: ftp25: mail111: RPC(远程程序呼叫)631: CUPS(列印服务功能)

假设我的主机有兴趣要侦测的是比较常见的 port 21, 22, 25及 80 时,那我如何透过 netstat 去侦测我的主机是否有开启这四个主要的网络服务端口呢?由於每个服务的关键字都是接在冒号『 : 』后面, 所以可以藉由撷取类似『 :80 』来侦测的!那我就可以简单的这样去写这个程序喔:

[root@www scripts]# vi sh10.sh#!/bin/bash# Program:# Using netstat and grep to detect WWW,SSH,FTP and Mail services.# History:# 2005/08/28VBirdFirst releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATH# 1. 先作一些告知的动作而已~echo "Now, I will detect your Linux server's services!"echo -e "The www, ftp, ssh, and mail will be detect! \n"# 2. 开始进行一些测试的工作,并且也输出一些资讯罗!testing=$(netstat -tuln | grep ":80 ")   # 侦测看 port 80 在否?if [ "$testing" != "" ]; thenecho "WWW is running in your system."fitesting=$(netstat -tuln | grep ":22 ")   # 侦测看 port 22 在否?if [ "$testing" != "" ]; thenecho "SSH is running in your system."fitesting=$(netstat -tuln | grep ":21 ")   # 侦测看 port 21 在否?if [ "$testing" != "" ]; thenecho "FTP is running in your system."fitesting=$(netstat -tuln | grep ":25 ")   # 侦测看 port 25 在否?if [ "$testing" != "" ]; thenecho "Mail is running in your system."fi

实际运行这支程序你就可以看到你的主机有没有启动这些服务啦!是否很有趣呢? 条件判断式还可以搞的更复杂!举例来说,在台湾当兵是国民应尽的义务,不过,在当兵的时候总是很想要退伍的! 那你能不能写个脚本程序来跑,让使用者输入他的退伍日期,让你去帮他计算还有几天才退伍?

由於日期是要用相减的方式来处置,所以我们可以透过使用 date 显示日期与时间,将他转为由 1970-01-01 累积而来的秒数, 透过秒数相减来取得剩余的秒数后,再换算为日数即可。整个脚本的制作流程有点像这样:

    先让使用者输入他们的退伍日期;再由现在日期比对退伍日期;由两个日期的比较来显示『还需要几天』才能够退伍的字样。

似乎挺难的样子?其实也不会啦,利用『date –date="YYYYMMDD" +%s』转成秒数后,接下来的动作就容易的多了!如果你已经写完了程序,对照底下的写法试看看:

[root@www scripts]# vi sh11.sh#!/bin/bash# Program:#You input your demobilization date, I calculate how many days#before you demobilize.# History:# 2005/08/29VBirdFirst releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATH# 1. 告知使用者这支程序的用途,并且告知应该如何输入日期格式?echo "This program will try to calculate :"echo "How many days before your demobilization date..."read -p "Please input your demobilization date (YYYYMMDD ex>20090401): " date2# 2. 测试一下,这个输入的内容是否正确?利用正规表示法罗~date_d=$(echo $date2 |grep '[0-9]\{8\}')   # 看看是否有八个数字if [ "$date_d" == "" ]; thenecho "You input the wrong date format...."exit 1fi# 3. 开始计算日期罗~declare -i date_dem=`date --date="$date2" +%s`    # 退伍日期秒数declare -i date_now=`date +%s`                    # 现在日期秒数declare -i date_total_s=$(($date_dem-$date_now))  # 剩余秒数统计declare -i date_d=$(($date_total_s/60/60/24))     # 转为日数if [ "$date_total_s" -lt "0" ]; then              # 判断是否已退伍echo "You had been demobilization before: " $((-1*$date_d)) " ago"elsedeclare -i date_h=$(($(($date_total_s-$date_d*60*60*24))/60/60))echo "You will demobilize after $date_d days and $date_h hours."fi

瞧一瞧,这支程序可以帮你计算退伍日期呢~如果是已经退伍的朋友, 还可以知道已经退伍多久了~哈哈!很可爱吧~脚本中的 date_d 变量宣告那个 /60/60/24 是来自於一天的总秒数 (24小时*60分*60秒) 。瞧~全部的动作都没有超出我们所学的范围吧~ ^_^ 还能够避免使用者输入错误的数字,所以多了一个正规表示法的判断式呢~ 这个例子比较难,有兴趣想要一探究竟的朋友,可以作一下课后练习题关於计算生日的那一题喔!~加油!

三亚呀——赴一个蓝天碧海。

Linux学习之第十九、条件判断

相关文章:

你感兴趣的文章:

标签云: