• 流程控制 -- 循环终止命令和数组总结


    img

    一、循环终止的特殊命令

    break、exit、continue、return的区别

    break n:如果省略n,则表示跳出'整个循环'、n表示跳出循环的层数,结束循环
    continue n:如果省略n,则表示跳出'本次循环',忽略本次循环的剩余代码,进入循环的下一个循环。n表示退到第n层继续循环,用于后面还有代码
    exit n:退出'当前shell',n为上一次程序执行的状态返回值,n也可以省略,在下一个shell里可通过"$?"接收exit n 的n值,结束进程
    return n :用于在函数里作为'函数值返回',以判断函数执行是否正确,在下一个shell里可通过"$?"接收exit n 的n值,return n的n值
    

    例0

    #!/bin/bash
    num=1
    while [ $num -lt 10 ];do
    if [ $num = 3 ];then
            break
    fi
            echo $num
            ((num++))
    done
    
    #!/bin/bash
    num=1
    while [ $num -lt 10 ];do
    if [ $num = 3 ];then
            ((num++))
            continue
    fi
            echo $num
            ((num++))
    done
    
    #break continel 之后的代码不会运行
    #条件,修改条件的话与break的区别就在于是否运行之后的代码
    #多层循环
    
    

    例一:

    #!/bin/bash
    if [ $# -ne 1 ];then
            echo $"usage:$0 {break|continue|exit|return}" 
            exit 1
    fi
    function test(){
            for ((i=0;i<5;i++))
            do
                    echo $i
                    if [ $i -eq 3 ];then
                            $*;
                    fi
            done
            echo "I am in func"
    }
    test $*
    func_ret=$?
    if [ $(echo $*|grep return | wc -l) -eq 1 ];then
            echo "return's exit status:$func_ret"
    fi
    echo "ok"
    

    效果如图:

    [root@mycentos shell]# sh 2.sh break
    0
    1
    2
    I am in func  #跳出for循环,后继续执行函数后面的代码
    ok        #执行脚本后面的代码
    
    [root@mycentos shell]# sh 2.sh continue
    0
    1
    2
    4
    I am in func   #将跳出for循环中本次循环,继续执行下次循环
    ok             #脚本后面的内容继续执行
    
    [root@mycentos shell]# sh 2.sh "exit 119"
    0
    1
    2  #直接跳出脚本,函数和脚本后面的内容不执行
    [root@mycentos shell]# echo $?
    119     退出程序时指定了"119",则执行脚本后获取"$?"的返回值就返回了"119",给当前的shell
    
    [root@mycentos shell]# sh 2.sh "return  119"
    0
    1
    2   #return 直接退出当前函数
    return''s exit status:119  #将119返回到了函数的外部脚本
    ok
    [root@mycentos shell]# echo $? 
    0            #执行脚本后的返回值为0,因为脚本中最后一条命令"ok"打印成功
    

    实战一:

    开发shell脚本实现服务器临时配置多个IP,并且可以随时撤销配置的所有IP.IP的地址范围为:10.0.2.1~10.0.2.16,其中10.0.2.10不能配置

    预备知识:
    一、给网卡配置额外IP的两种方式
    1.)ifconfig配置别名IP的方式
    ifconfig eth0:0 10.0.2.10/24 up #添加IP
    ifconfig eth0:0 10.0.2.10/24 down #删除IP
    2.)使用ip配置辅助IP的方式:
    ip addr add 10.0.2.11/24 dev eth0 label eth0:0 #添加ip
    ip addr del 10.0.2.11/24 dev eth0 label eth0:0 #删除ip

    简略版:
    #!/bin/bash
    for num in $(seq 16)
    do
            if [ $num -eq 10 ];then
                    continue
            else
                    #ip addr add  10.0.2.$num/24 dev eth0 label eth0:$num  <==这个也可以
                    ifconfig eth0:$num 10.0.2.$num/24 down
            fi
    done
    
    #注意添加的时候不要添加本机ip的主机位
    #注意要排除网卡和网关的ip
    
    简单版本:
    #!/bin/bash
    [ -f /etc/init.d/functions ] && . /etc/init.d/functions || echo /etc/init.d/functions 不存在
    [ $# -eq 1 ] || echo "usage:$0 {start|stop|restart}"
    RETVAL=0
    function add(){
            for ip in {1..16}
            do
                    if [ $ip -eq 10 ];then
                            continue
                    else
                            ifconfig eth0:$ip 10.0.2.${ip}/24 up
                            RETVAL=$?
                            if [ $RETVAL -eq 0 ];then
                                    action "add $ip" /bin/true
                            else
                                    action "add $ip" /bin/false
                            fi
                    fi
            done
            return $RETVAL
    }
    function del(){
            for ip in {1..16}
            do
                    if [ $ip -eq 10 ];then
                            continue
                    else
                            ifconfig eth0:$ip 10.0.2.${ip}/24 down
                            RETVAL=$?
                            if [ $RETVAL -eq 0 ];then
                                    action "del $ip" /bin/true
                            else
                                    action "del $ip" /bin/false
                            fi
                    fi 
            done
            return $RETVAL
    }
    case "$1" in
            start)
                    add
                    RETVAL=$?
                    ;;
            stop)
                    del
                    RETVAL=$?
                    ;;
            restart)
                    del
                    sleep 2
                    add
                    RETVAL=$?
                    ;;
            *)
                    printf $"usage:$0 {start|stop|restart}"
    esac
    exit $RETVAL
    注:
        一、此版本代码冗余多,可以将冗余代码组合
    
    去除代码冗余版:
    #!/bin/bash
    [ -f /etc/init.d/functions ] && . /etc/init.d/functions || echo /etc/init.d/functions 不存在
    [ $# -eq 1 ] || echo "usage:$0 {start|stop|restart}"
    RETVAL=0
    function op(){
            if [ "$1" == "del" ];then   #空格不要忘了
                    list=$(echo {16..1})#从后往前删除
            else
                    list=$(echo {1..16})
            fi
            for ip in $list
             do
                    if [ $ip -eq 10 ];then
                            continue   #跳出此次循环
                    else
                            ip addr $1 10.0.2.$ip/24 dev eth0 label eth0:$ip &>/dev/null
                            RETVAL=$?
                            if [ $RETVAL -eq 0 ];then
                                    action "$1 $ip" /bin/true
                            else
                                    action "$1 $ip" /bin/false
                            fi
                    fi
             done
            return $RETVAL
    }
    case "$1" in
            start)
                    op add  #注意传参到op函数中去
                    RETVAL=$?
                    ;;
            stop)
                    op del
                    RETVAL=$?
                    ;;
            restart)
                    op del
                    sleep 2
                    op add
                    RETVAL=$?
                    ;;
            *)
                    printf $"usage:$0 {start|stop|restart}"
    esac
    exit $RETVAL
    

    效果如下:

    [root@mycentos ~]# sh 1.sh start
    add 1                                                      [  OK  ]
    add 2                                                      [  OK  ]
    add 3                                                      [  OK  ]
    add 4                                                      [  OK  ]
    add 5                                                      [  OK  ]
    add 6                                                      [  OK  ]
    add 7                                                      [  OK  ]
    add 8                                                      [  OK  ]
    add 9                                                      [  OK  ]
    add 11                                                     [  OK  ]
    add 12                                                     [  OK  ]
    add 13                                                     [  OK  ]
    add 14                                                     [  OK  ]
    add 15                                                     [  OK  ]
    add 16                                                     [  OK  ]
    使用ifconfig可查看eth0的虚拟ip
    

    实战二:

    已知下面字符串是将RANDOM随机数采用md5sum加密后任意取出的连续10位结果,请破解这些字符串对应的md5sum前对的字符串的数字?
    "4fe8bf20ed"

    一、预备知识
    RANDOM的范围是:0~32767
    二、思路:
    1.)先将RANDOM随机的所有可能写成字典
    2.)用脚本做密码匹配

    1)RANDOM字典的生成
    #!/bin/bash
    for n in {0..32767}
    do
            echo "$(echo $n | md5sum) : $n" >> zhiwen.txt
    done
    echo "ok"
    2)匹配密码
    #!/bin/bash
    
    md5char="4fe8bf20ed" #要匹配的字符串
    
    while read line #变量是line
    do 
            if [ $(echo $line | grep $md5char | wc -l) -eq 1 ];then
                    echo $line 
                    break  #匹配到后就退出程序
            fi
    
    done <zhiwen.txt #按行读取字典
    
    将上述代码合并
    #!/bin/bash
    
    >zidian.txt #清空字典文件
    for n in {0..32767}
    do
            nohub echo "$(echo $n |md5sum) : $n" >>zidian.txt  & #此处不能是">"
    done
    echo "input ok"
    
    md5char="4fe8bf20ed" #要破解密码
    
    while read line
    do
    		echo $line | grep $md5char >/dev/null
            if [ $? -eq 0 ];then 
                    echo $line
                    break
            fi
    
    done <zidian.txt
    
    #此脚本只能破解 整型数字md5sum加密
    #如果不用完整的加密码匹配的话,可能匹配不到
    #如果使用完整的加密码匹配的话,一定可以匹配到对应的数字
    

    效果如图:

    [root@mycentos shell]# sh 7.sh 
    1dcca23355272056f04fe8bf20edfce0 - : 5
    

    二、数组

    数组的操作

    1.定义数组:
    方式一:用小括号将变量值括起来赋值给数组变量,每个变量之间要用空格进行分格
    [root@mycentos shell]# array=(1 2 3)
    [root@mycentos shell]# echo ${array[*]}  #打印单个数组元素时用"${数组名[下标]}",当未指定数组下标时,数组的下标将从0开始。
    1 2 3
    方式二:用小括号将变量括起来,同时1采用键值对的形式赋值
    array=([1]=one [2]=two [3]=three)
    小括号里对应的数字为数组下标,等号后面的内容为下标对应的数组变量的值。
    [root@mycentos shell]# array=([1]=one [2]=twe [3]=three)
    [root@mycentos shell]# echo ${array[1]}  
    one
    [root@mycentos shell]# echo ${array[2]}
    twe
    [root@mycentos shell]# echo ${array[3]}
    three
    [root@mycentos shell]# echo ${array[*]}
    one twe three
    
    方法三:动态的定义数组变量,并使用命令的输出结果作为数组内容
    array=($(命令))
    或
    array=(`命令`)
    
    [root@mycentos Desktop]# touch array/{1..3}.txt
    [root@mycentos Desktop]# ls -l array/
    total 0
    -rw-r--r--. 1 root root 0 Nov 15 14:44 1.txt
    -rw-r--r--. 1 root root 0 Nov 15 14:44 2.txt
    -rw-r--r--. 1 root root 0 Nov 15 14:44 3.txt
    [root@mycentos Desktop]# array=($(ls array/))
    [root@mycentos Desktop]# echo ${array[*]}
    1.txt 2.txt 3.txt
    ------------------------------------------------------------------------------------------------
    2.打印数组长度
    echo {#数组名[*]}
    数组是特殊的变量,变量子串的知识也试用。
    ------------------------------------------------------------------------------------------------
    3.数组的赋值:
    数组名[下标]=值
    ------------------------------------------------------------------------------------------------
    4.数组的删除:
    由于数组本质上是变量,则可通过unset 数组[下标]来清除相应的数组元素,如果不带下标,则表示清除整个数组的所有数据。
    ------------------------------------------------------------------------------------------------
    5.数组内容的截取和替换:
    [root@mycentos ~]# array=(1 2 3 4 5)
    [root@mycentos ~]# echo ${array[*]:1:3}   #从下标为1的元素开始截取3个数组元素
    2 3 4
    [root@mycentos ~]# array=({a..z})
    [root@mycentos ~]# echo ${array[*]}
    a b c d e f g h i j k l m n o p q r s t u v w x y z
    [root@mycentos ~]# echo ${array[*]:1:2}  #从下标为1的元素开始截取2个数组元素
    b c 
    
    [root@mycentos ~]# array=(1 2 3 4 5)
    [root@mycentos ~]# echo ${array[*]/1/b}  #把数组的1替换成b,原来数组被修改和sed很像
    b 2 3 4 5
    
    替换方法:
    ${数组名[@或*]/查找字符/替换字符},该操作"并不会改变"原先数组的内容。
    

    例一:
    使用循环批量输出数组的元素

    方式一:C语言型打印数组元素,索引取值
    #!/bin/bash
    array=(1 2 3 4 5)
    for ((i=0;i<${#array[*]};i++))
    do
            echo ${array[i]}
    done
    方式二:
    普通循环打印数组元素,直接取值
    #!/bin/bash
    array=(1 2 3 4 5)
    for n in ${array[*]} #<==${array[*]}表示输出数组的所有元素,相当于列表数组元素
    do
            echo $n
    done
    方式三:,索引取值
    #!/bin/bash
    array=(1 2 3 4 5)
    i=0
    while ((i<${#array[*]}))
    do
            echo ${array[i]}
            ((i++))
    done
    
    #普通数组的取值
    	1.直接取值,echo ${array[*]}
    	2.索引取值,echo ${!array[*]},再使用for循环索引取值
    #关联数组的取值
    	1.直接取值,echo ${array[*]}
    	2.通过key取值,echo ${!array[*]},再使用for循环索引取值
    

    例二:通过竖向列举法定义数组元素批量打印,索引取值

    #!/bin/bash
    array=(
    oldboy
    oldgirl
    xiaoming
    xiaoqiang
    )
    for ((i=0;i<${#array[*]};i++))
    do
            echo "this is num $i,then content is ${array[$i]}"
    done
    echo "array len:${#array[*]}"
    

    结果如图:

    [root@mycentos arr]# sh 4.sh 
    this is num 0,then content is oldboy
    this is num 1,then content is oldgirl
    this is num 2,then content is xiaoming
    this is num 3,then content is xiaoqiang
    array len:4
    

    例三:
    将命令结果作为数组元素定义并打印,索引取值

    #!/bin/bash
    dir=($(ls ./*.txt))
    for ((i=0;i<${#dir[*]};i++))
    do
            echo "this is NO.$i,filename is ${dir[$i]}"
    done
    

    结果如图:

    [root@mycentos arr]# sh 5.sh 
    this is NO.0,filename is ./1.txt
    this is NO.1,filename is ./2.txt
    this is NO.2,filename is ./3.txt
    this is NO.3,filename is ./4.txt
    

    关于数组的总结:

    1).定义:
    静态 array=(1 2 3)
    动态 array=($(ls))
    2).赋值:array[3]=4
    3).打印:${array[*]}或${array[@]}
        数组长度:${#array[@]}或${#array[*]}
        单个元素:${array[i]}
    4).循环打印
    #!/bin/bash
    arr=(
            10.0.0.11
            10.0.0.22
            10.0.0.33
    )
    #<==C语言循环打印,索引取值
    for ((i=0;i<${#arr[*]};i++))
    do
            echo "${arr[i]}"
    done
    echo '-----------------------------------'
    
    #<==普通循环打印,直接打印
    for n in ${arr[*]}
    do
            echo "$n"
    done
    

    实战三

    利用for循环打印下面这句话不大于6个字母的单词(普通数组)
    I am lodboy teacher welcome to oldboy training class

    方式一(数组实现):
    #!/bin/bash
    arr=(I am oldboy teacher welcome to oldboy training class)
    
    for ((i=0;i<${#arr[*]};i++))
    do
            #if [ $(expr length ${arr[i]}) -lt 6 ];then
            #       echo ${arr[i]}
            #fi
    
            if [ ${#arr[i]} -le 6 ];then
                    echo ${arr[i]}
            fi
    done
    
    方式二(列表实现):#!/bin/bash
    for word in I am oldboy teacher welcome to oldboy training class
    do
            if [ ${#word} -lt 6 ];then
    
                    echo $word
            fi
    
    done
    
    方法三(awk循环):
    [root@mycentos arr]# char="I am oldboy teacher welcome to oldboy training class"
    [root@mycentos arr]# echo $char | awk '{for(i=1;i<=NF;i++) if(length($i)<6)print $i}' 
    I
    am
    to
    class
    

    实战四

    检测多个网站地址是否正常
    要求:
    1)使用shell数组的方法实现,检测策略尽量使用模拟用户访问
    2)每10秒进行一次全部检测,无法访问的输出报警
    3)待检测的地址如下
    http://www.baidu.com
    http://www.sina.com
    http://www.qq.com
    http://www.1.com

    思路:
    一、网站放到数组中
    二、编写URL检测脚本,传入数组的元素,即URL
    三、组合实现整个案例,编写main的主函数(即执行函数),每隔10秒检查一次

    #!/bin/bash
    
    . /etc/init.d/functions
    check_count=0
    
    urlArr=(
            http://www.linuxprobe.com
            http://www.sina.com
            http://www.a.co
            http://www.baidu.com
    )
    
    function wait(){  #定义倒计数3、2、1函数
            echo -n "3秒后,执行检查URL的操作"
            for ((i=0;i<3;i++))
            do
                    echo -n '.';sleep 1
            done
            echo
    
    }
    
    function check_url(){
            wait  #执行倒计时函数
            for ((i=0;i<$(echo ${#urlArr[*]});i++))
            do
                    wget -o /dev/null -T 5  --tries=1 --spider  ${urlArr[i]} &>/dev/null
                    if [ $? -eq 0 ];then
                            action "${urlArr[i]}" /bin/true
                    else
                            action "${urlArr[i]}" /bin/false
                    fi
            done
            ((chenk_count++)) #检测次数
    }
    
    function main(){
            while true
            do
                    check_url
                    echo "-------check count end:${check_count}-----"
                    sleep 1
            done
    }
    
    main
    
    #echo -n 不换行输出
    

    效果如图:

    img

  • 相关阅读:
    Java的Socket通信----通过 Socket 实现 TCP 编程之多线程demo(2)
    MySQL 数据备份与还原
    java实现时钟方法汇总
    java实现二叉树demo
    java实现心型、99乘法demo
    显示本月日历demo
    打开图片并显示在面板上demo
    ArraySort--冒泡排序、选择排序、插入排序工具类demo
    类的实例化顺序
    StringsUtil字符串工具类---灵活截取
  • 原文地址:https://www.cnblogs.com/syy1757528181/p/13603816.html
Copyright © 2020-2023  润新知