zoukankan      html  css  js  c++  java
  • 流程控制 -- 循环终止命令和数组总结

    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

  • 相关阅读:
    BZOJ 3744 Gty的妹子序列
    BZOJ 3872 Ant colony
    BZOJ 1087 互不侵犯
    BZOJ 1070 修车
    BZOJ 2654 tree
    BZOJ 3243 向量内积
    1003 NOIP 模拟赛Day2 城市建设
    CF865D Buy Low Sell High
    CF444A DZY Loves Physics
    Luogu 4310 绝世好题
  • 原文地址:https://www.cnblogs.com/syy1757528181/p/13603816.html
Copyright © 2011-2022 走看看