zoukankan      html  css  js  c++  java
  • 第十三章、学习 Shell Scripts 条件判断式


    利用 if .... then

    • 单层、简单条件判断式
    if [ 条件判断式 ]; then
    	当条件判断式成立时,可以进行的命令工作内容;
    fi   <==将 if 反过来写,就成为 fi !结束 if 之意!
    
    • && 代表 AND ;
    • || 代表 or ;
    [ "$yn" == "Y" -o "$yn" == "y" ]
    上式可替换为
    [ "$yn" == "Y" ] || [ "$yn" == "y" ]
    [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 release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    
    read -p "Please input (Y/N): " yn
    
    if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
    	echo "OK, continue"
    	exit 0
    fi
    if [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
    	echo "Oh, interrupt!"
    	exit 0
    fi
    echo "I don't know what your choice is" && exit 0
    

    • 多重、复杂条件判断式
    # 一个条件判断,分成功进行与失败进行 (else)
    if [ 条件判断式 ]; then
    	当条件判断式成立时,可以进行的命令工作内容;
    else
    	当条件判断式不成立时,可以进行的命令工作内容;
    fi
    
    # 多个条件判断 (if ... elif ... elif ... else) 分多种不同情况运行
    if [ 条件判断式一 ]; then
    	当条件判断式一成立时,可以进行的命令工作内容;
    elif [ 条件判断式二 ]; then
    	当条件判断式二成立时,可以进行的命令工作内容;
    else
    	当条件判断式一与二均不成立时,可以进行的命令工作内容;
    fi
    
    [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 release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    
    read -p "Please input (Y/N): " yn
    
    if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
    	echo "OK, continue"
    elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
    	echo "Oh, interrupt!"
    else
    	echo "I don't know what your choice is"
    fi
    

     一般来说,如果你不希望使用者由键盘输入额外的数据时, 让使用者在下达命令时就将参数带进去! 现在我们想让使用者输入『 hello 』这个关键字时,利用参数的方法可以这样依序设计:

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

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

    [root@www scripts]# vi sh09.sh
    #!/bin/bash
    # Program:
    #	Check $1 is equal to "hello"
    # History:
    # 2005/08/28	VBird	First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    
    if [ "$1" == "hello" ]; then
    	echo "Hello, how are you ?"
    elif [ "$1" == "" ]; then
    	echo "You MUST input parameters, ex> {$0 someword}"
    else
    	echo "The only parameter is 'hello', ex> {$0 hello}"
    fi
    

    netstat命令可以查询到目前主机有开启的网络服务端口 (service ports)

    [root@www ~]# netstat -tuln
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address     Foreign Address   State
    tcp        0      0 0.0.0.0:111       0.0.0.0:*         LISTEN
    tcp        0      0 127.0.0.1:631     0.0.0.0:*         LISTEN
    tcp        0      0 127.0.0.1:25      0.0.0.0:*         LISTEN
    tcp        0      0 :::22             :::*              LISTEN
    udp        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与端口对应)』那个栏位,他代表的是本机所启动的网络服务!若为 127.0.0.1 则是仅针对本机开放,若是 0.0.0.0 或 ::: 则代表对整个 Internet 开放。 每个端口 (port) 都有其特定的网络服务,几个常见的 port 与相关网络服务的关系是:

    • 80: WWW
    • 22: ssh
    • 21: ftp
    • 25: mail
    • 111: 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/28	VBird	First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    
    # 1. 先作一些告知的动作而已~
    echo "Now, I will detect your Linux server's services!"
    echo -e "The www, ftp, ssh, and mail will be detect! 
    "
    
    # 2. 开始进行一些测试的工作,并且也输出一些资讯罗!
    testing=$(netstat -tuln | grep ":80 ")   # 侦测看 port 80 在否?
    if [ "$testing" != "" ]; then
    	echo "WWW is running in your system."
    fi
    testing=$(netstat -tuln | grep ":22 ")   # 侦测看 port 22 在否?
    if [ "$testing" != "" ]; then
    	echo "SSH is running in your system."
    fi
    testing=$(netstat -tuln | grep ":21 ")   # 侦测看 port 21 在否?
    if [ "$testing" != "" ]; then
    	echo "FTP is running in your system."
    fi
    testing=$(netstat -tuln | grep ":25 ")   # 侦测看 port 25 在否?
    if [ "$testing" != "" ]; then
    	echo "Mail is running in your system."
    fi
    

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

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

    利用『 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/29	VBird	First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export 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" == "" ]; then
    	echo "You input the wrong date format...."
    	exit 1
    fi
    
    # 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"
    else
    	declare -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
    

    利用 case ..... esac 判断
    case  $变量名称 in   <==关键字为 case ,还有变量前有钱字号
      "第一个变量内容")   <==每个变量内容建议用双引号括起来,关键字则为小括号 )
    	程序段
    	;;            <==每个类别结尾使用两个连续的分号来处理!
      "第二个变量内容")
    	程序段
    	;;
      *)                  <==最后一个变量内容都会用 * 来代表所有其他值
    	不包含第一个变量内容与第二个变量内容的其他程序运行段
    	exit 1
    	;;
    esac                  <==最终的 case 结尾!『反过来写』!
    
    [root@www scripts]# vi sh09-2.sh
    #!/bin/bash
    # Program:
    # 	Show "Hello" from $1.... by using case .... esac
    # History:
    # 2005/08/29	VBird	First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    
    case $1 in
      "hello")
    	echo "Hello, how are you ?"
    	;;
      "")
    	echo "You MUST input parameters, ex> {$0 someword}"
    	;;
      *)   # 其实就相当於万用字节,0~无穷多个任意字节之意!
    	echo "Usage $0 {hello}"
    	;;
    esac
    
    /etc/init.d/syslog restart

    一般来说,使用『 case $变量 in 』这个语法中,当中的那个『 $变量 』大致有两种取得的方式:

    • 直接下达式:例如上面提到的,利用『 script.sh variable 』 的方式来直接给予 $1 这个变量的内容,这也是在 /etc/init.d 目录下大多数程序的设计方式。

    • 互动式:透过 read 这个命令来让使用者输入变量的内容。

    让使用者能够输入 one, two, three , 并且将使用者的变量显示到萤幕上,如果不是 one, two, three 时,就告知使用者仅有这三种选择。

    [root@www scripts]# vi sh12.sh
    #!/bin/bash
    # Program:
    #	This script only accepts the flowing parameter: one, two or three.
    # History:
    # 2005/08/29	VBird	First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    
    echo "This program will print your selection !"
    # read -p "Input your choice: " choice # 暂时取消,可以替换!
    # case $choice in                      # 暂时取消,可以替换!
    case $1 in                             # 现在使用,可以用上面两行替换!
      "one")
    	echo "Your choice is ONE"
    	;;
      "two")
    	echo "Your choice is TWO"
    	;;
      "three")
    	echo "Your choice is THREE"
    	;;
      *)
    	echo "Usage $0 {one|two|three}"
    	;;
    esac
    

    利用 function 功能

     

    function fname() {
    	程序段
    }
    

    因为 shell script 的运行方式是由上而下,由左而右, 因此在 shell script 当中的 function 的配置一定要在程序的最前面, 这样才能够在运行时被找到!

    [root@www scripts]# vi sh12-2.sh
    #!/bin/bash
    # Program:
    #	Use function to repeat information.
    # History:
    # 2005/08/29	VBird	First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    
    function printit(){
    	echo -n "Your choice is "     # 加上 -n 可以不断行继续在同一行显示
    }
    
    echo "This program will print your selection !"
    case $1 in
      "one")
    	printit; echo $1 | tr 'a-z' 'A-Z'  # 将参数做大小写转换!
    	;;
      "two")
    	printit; echo $1 | tr 'a-z' 'A-Z'
    	;;
      "three")
    	printit; echo $1 | tr 'a-z' 'A-Z'
    	;;
      *)
    	echo "Usage $0 {one|two|three}"
    	;;
    esac
    
       

     function 也是拥有内建变量的, 函数名称代表示 $0 ,而后续接的变量也是以 $1, $2...

    [root@www scripts]# vi sh12-3.sh
    #!/bin/bash
    # Program:
    #	Use function to repeat information.
    # History:
    # 2005/08/29	VBird	First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    
    function printit(){
    	echo "Your choice is $1"   # 这个 $1 必须要参考底下命令的下达
    }
    
    echo "This program will print your selection !"
    case $1 in
      "one")
    	printit 1  # 请注意, printit 命令后面还有接参数!
    	;;
      "two")
    	printit 2
    	;;
      "three")
    	printit 3
    	;;
      *)
    	echo "Usage $0 {one|two|three}"
    	;;
    esac
    

     

  • 相关阅读:
    无法跨越程序集边界使用程序集,因为该成员包含的某个类型具有一个为嵌入互操作类型的泛型类型参数。
    arcengine右键实现new group layer的功能
    winform进度条
    arcgisengine实现矩形转面
    win10 SVN不能显示图标
    关于VS打包程序无法弹出主界面的问题
    ArcGIS Javascript 异常之No 'Access-Control-Allow-Origin' header
    ArcGIS JavaScript API异常之onExtentChange事件覆盖onClick事件
    ArcGIS AddIN 之 DockPanel 界面空白
    关于JQuery设置checkbox checked 的问题
  • 原文地址:https://www.cnblogs.com/ghgyj/p/3983420.html
Copyright © 2011-2022 走看看