程序员人生 网站导航

shell学习笔记之七(循环)

栏目:服务器时间:2015-06-04 07:54:37
循环
    shell中的循环主要有for,while,untile,select
    for
        1、列表for循环
            for VARIABLE in (list)
            do
                command
            done
            例:循环打印john喜欢的水果
                for fruit in apple orange banana pear
                do
                    echo  "$fruit is John's favorite"
                done
                echo "No more fruits."
            注意:
                in里面可以是任意命令的标准输出
                如:
                    fruits="apple orange banana pear"
                    seq 1 2 100     #产生1到100的奇数数列
                    ls
                    1..5    #表示1 2 3 4 5
                #!/bin/bash
                echo '变量作为in的参数'
                fruits="apple orange pear"
                for fruit in ${fruits}
                do
                    echo $fruit
                done
                echo "序列作为in的参数"
                for var in 1 2 3 4 5
                do
                    echo $var
                done
                echo "seq产生的序列作为in的参数"
                #declare -i total=0
                total=0
                for var in $(seq 1 2 100)
                do
                    #total+=$var
                    #(( total += var ))     #注意算数运算的写法,1共3种写法都可以实现赋值
                    let "total+=var"
                done
                echo "1+3+5+...+99 is $total"
                echo "ls的结果作为in的参数"
                for var in $(ls)
                do
                    ls -l $var
                done
        2、不带列表的for循环
                for variable
                do
                    command
                done
                注意:使用不带列表的for,需要在运行脚本时通过参数的方式给for传递变量值
                #for.sh
                #!/bin/bash
                for var
                do
                    echo $var
                done
                # . ./for.sh 1 2 3
                可读性差,可使用$@实现上面的功能
                改进:
                    #!/bin/bash
                    for var in $@
                    do
                        echo $var
                    done
        3、类Cfor循环
                for ((expression ;expression2; expression3))
                do
                    command
                done
                例:
                    #!/bin/bash
                    for (( i=0; i<10; i++ ))    #这里没有甚么空格的要求,为了美观,使用空格
                    do
                        echo -n "$i "
                    done
        4、for的无穷循环
                for((;1;))
                do
                    echo
                done
    while
        while expression
        do
            command
        done
        例:
            1、#输出1到10的数字序列
                #!/bin/bash
                declare -i count=0
                while [[ $count -lt 10 ]]
                do
                    echo "$count"
                    count+=1
                done
            2、#求1⑴00之和
            #求1⑴00之间奇数之和
                #!/bin/bash
                declare -i sum01=0
                declare -i sum02=0
                declare -i i=1
                declare -i j=1
                while [[ i -le 100 ]]
                do
                    sum01+=i;
                    j=i%2;
                    #if [[ $(( i%2 )) -ne 0 ]];then
                    if [[ j -ne 0 ]];then
                        sum02+=i;
                    fi
                    ((i++));#这里不可1写$((i++))
                done
                echo $sum01
                echo $sum02
            3、#猜数字
                #!/bin/bash
                num=8
                echo "Input a number in 1 to 10:"
                #体会read的用法
                while read guass
                do
                    if [[ $guass -eq $num ]];then
                        echo "Right."
                        break
                    else
                        echo "Wrong.Try Again"
                    fi
                done
            4、按行读取文件
                cat student_info.txt
                John    30  Boy
                Sue     28  Girl
                Wang    25  Boy
                Xu  23  Girl
                解法1:
                    #!/bin/bash
                    while read line
                    do
                        name=`echo $line | cut -d ' ' -f1` #echo输出line以后Tab会变成空格,所以使用cut的时候需要指定分割符(-d ' ')
                        age=`echo $line | cut -d ' ' -f2`  #也能够使用awk   awk '{print $n}',awk的分割符是空格(' ')或Tab
                        sex=`echo $line | cut -d ' ' -f3`
                        echo "My name is $name,I'm $age years old,I'm a $sex"
                    done < student_info.txt
                    注意:全部思路是清晰的,重点是怎样读取文件,选用甚么命令处理行。比较而言,脚本比编辑1个高级语言程序要简洁很多
                解法2:
                    #!/bin/bash
                    cat student_info.txt | while read line
                    do
                        name=`echo $line | cut -d ' ' -f1`
                        age=`echo $line | cut -d ' ' -f2`
                        sex=`echo $line | cut -d ' ' -f3`
                        echo "My name is $name,I'm $age years old,I'm a $sex"
                    done
                两种解法功能相同,但是有细微差别。使用重定向的while只会产生1个shell,而使用管道的脚本在运行时会产生3个shell,第1个shell是cat(运行很快,致使没法使用ps命令抓到),第2个shell是管道,第3个shell是while
            5、无穷循环
                #方法1
                while ((1))
                do
                    command
                done
                #方法2
                while true
                do
                    command
                done
                #方法3
                while :     
                do
                    command
                done
                例:检测系统进程,
                    #!/bin/bash
                    while true
                    do
                        ATD_STATUS=`service atd status | grep running`
                        if [[ -z "$ATD_STATUS" ]];then
                            echo "ATD is stopped , try to restart."
                            service atd restart #在脚本中,如果不需要命令的返回值,则直接写命令便可,而不需要用$()命令替换
                        else
                            echo "ATD is running,wait 5 sec until next check"
                        fi
                        sleep 5 #延迟函数,单位是秒(s)
                    done
    until
        结构:
            until expression
            do
                command
            done
        描写:
            运行前测试,测试结果为false时继续履行,为true时退出
        例:
            #使用until计算1到100的和和1⑴00的奇数和
            #!/bin/bash
            declare -i sum01=0
            declare -i sum02=0
            declare -i i=0
            until [[ i -gt 100 ]]
            do
                sum01+=i
                if [[ $[i%2] -ne 0 ]];then
                    sum02+=i
                fi
                ((i++));
            done
            echo "sum01=$sum01"
            echo "sum02=$sum02"

        until的无穷循环
            until ((0))
            do
                command
            done
            until false
            do
                command
            done
    select循环
        结构:
            select Menu in (list)
            do
                command
            done
        描写:
            菜单扩大循环方式,语法和带列表的for循环非常类似
        例:
            1、判断用户的选择
                #!/bin/bash
                echo "Which car do you prefer?"
                select car in Benz Audi VolksWagen
                do
                    break   #注意这个break,没有这个会1直处于选择状态
                done
                echo "You chose $car"
                注解:select有判断用户输入的功能,所以select常常和case语句合并使用,
            2、联合使用select和case
                #!/bin/bash
                select var in Mon Tue Wed Thu Fri Sat Sun
                do
                    case $var in   #case是不需要break语句的
                        Mon)
                            echo "Today is Monday" 
                            break ;;
                        Tue)
                            echo "Today is Tuesday" 
                            break;;
                        Wed)
                            echo "Today is Wednesday" 
                            break ;;
                        Thu)
                            echo "Today is Thursday" 
                            break ;;
                        Fri)
                            echo "Today is Friday" 
                            break ;;
                        Sat|Sun)
                            echo "You can have a rest day" 
                            break;;
                        *)
                            echo "Unknown input.Try again" ;;
                    esac
                done
    嵌套循环
        例:打印99乘法表
            #!/bin/bash
            declare -i i=1;
            declare -i j=1;
            declare -i k=0
            for (( i = 1; i <= 9; i++ ))
            do
                for (( j = 1; j <= i; j++ ))
                do
                    k=$i+$j
                    #let "k=i+j"
                    echo -ne $j"*"$i"="$k"	"
                    #echo -ne $j"*"$i"="$(($i+$j))"	"
                    #echo -ne $j"*"$i"="$[$j*$i]"	"
                    #这里看到了多种表达式求值
                done
                echo 
            done
            注意:
                1、for的类C写法,不需要$符号,也不需要使用-le之类的
                2、echo输出制表符,需要使用-e参数,这表示有转义字符时转义。没有-e会原样输出而不解释转义字符
                3、表达式求值
                4、自行改编成其他循环版本的99乘法表
        扩大:使用sed和awk输出99乘法表
            #!/bin/bash
            seq 9 |sed "H;g"|awk -v RS="" '{
                for(i=1;i<=NF;i++){
                    j=i*NR;
                    printf("%d*%d=%d	",i,NR,i*NR);
                }
                printf("
");
            }'
    循环控制
        break
        continue    
        不做详细介绍,跟高级语言1样,唯1的区分是break,continue后面可以接数字,表示跳出嵌套层数,和Java中的标签类似。
        例:打印素数
             解法1:
            #!/bin/bash
            declare -i i=1
            declare -i j=2
            for (( i = 1; i < 100 ; i++ ))
            do
                for (( j = 2; j < i ;j++ ))
                do
                    if ! (($i%$j));then    #注意! 和(())扩大运算之间有空格
                        break;
                    fi
                done
                if [[ $j -eq $i ]];then
                    echo -ne "$i	"
                fi
            done
            echo
            解法2: 
            #!/bin/bash
            declare -i i=1
            declare -i j=2
            for (( i = 1; i < 100 ; i++ ))
            do
                for (( j = 2; j < i ;j++ ))
                do
                    if ! (($i%$j));then   #注意! 和(())扩大运算之间有空格
                        continue 2; #continue后面的数字表示跳出的嵌套数
                    fi
                done
                if [[ $j -eq $i ]];then
                    echo -ne "$i	"
                fi
            done
            echo 
------分隔线----------------------------
------分隔线----------------------------

最新技术推荐