linux 命令詳解 二十七

    4.  循環語句:
    Bash Shell
中主要提供了三種循環方式:forwhileuntil
    for循環聲明格式:
    for variable in word_list
    do
        command
    done
    
見如下示例腳本:
    /> cat > test7.sh
    for score in math english physics chemist   #for將循環讀取in後面的單詞列表,類似於Javafor-each
    do
        echo "score = $score"
    done
    echo "out of for loop"
    CTRL+D
    /> . ./test7.sh
    score = math
    score = english
    score = physics
    score = chemist
    out of for loop

    /> cat > mylist   #構造數據文件
    tom
    patty
    ann
    jake
    CTRL+D
    /> cat > test8.sh
    #!/bin/sh
    for person in $(cat mylist)                 #for將循環讀取cat mylist命令的執行結果。
    do
        echo "person = $person"
    done
    echo "out of for loop."
    CTRL+D
    /> . ./test8.sh
    person = tom
    person = patty
    person = ann
    person = jake
    out of for loop.

    /> cat > test9.sh
    for file in test[1-8].sh                        #for將讀取test1-test8,後綴爲.sh的文件
    do
        if [ -f $file ]                              #判斷文件在當前目錄是否存在。
        then
            echo "$file exists."
        fi
    done
    CTRL+D
    /> . ./test9.sh
    test2.sh exists.
    test3.sh exists.
    test4.sh exists.
    test5.sh exists.
    test6.sh exists.
    test7.sh exists.
    test8.sh exists.

    /> cat > test10.sh
    for name in $*                                  #讀取腳本的命令行參數數組,還可以寫成for name的簡化形式。
    do
        echo "Hi, $name"
    done
    CTRL+D
    /> . ./test10.sh stephen ann
    Hi, stephen
    Hi, ann

    while循環聲明格式:
    while command  #如果command命令的執行結果爲0,或條件判斷爲真時,執行循環體內的命令。
    do
        command
    done
    
見如下示例腳本:
    /> cat > test1.sh  
    num=0
    while (( num < 10 ))               #等同於 [ $num -lt 10 ]
    do
        echo -n "$num "
        let num+=1
    done
    echo -e "\nHere's out of loop."
    CTRL+D
    /> . ./test1.sh
    0 1 2 3 4 5 6 7 8 9
 
    Here's out of loop.

    /> cat > test2.sh
    go=start
    echo Type q to quit.
    while [[ -n $go ]]                     #等同於[ -n "$go" ],如使用該風格,$go需要被雙引號括起。
    do
        echo -n How are you.
        read word
        if [[ $word == [Qq] ]]      #等同於[ "$word" = Q -o "$word" = q ]
        then
            echo Bye.
            go=                        #go變量的值置空。
        fi
    done
    CTRL+D
    /> . ./test2.sh
    How are you.
 Hi
    How are you.
 q
    Bye.

    until循環聲明格式:
    until command                         #其判斷條件和while正好相反,即command返回非0,或條件爲假時執行循環體內的命令。
    do
        command
    done
    
見如下示例腳本:
    /> cat > test3.sh
    until who | grep stephen           #循環體內的命令將被執行,直到stephen登錄,即grep命令的返回值爲0時才退出循環。
    do
        sleep 1
        echo "Stephen still doesn't login."
    done
    CTRL+D

    shift命令聲明格式:shift [n]
    shift
命令用來把腳本的位置參數列表向左移動指定的位數(n),如果shift沒有參數,則將參數列表向左移動一位。一旦移位發生,被移出列表的參數就被永遠刪除了。通常在while循環中,shift用來讀取列表中的參數變量。
    
見如下示例腳本:
    /> set stephen ann sheryl mark #設置4個參數變量。
    /> shift                                    #向左移動參數列表一次,將stephen移出參數列表。
    /> echo $*
    ann sheryl mark
    /> shift 2                                 #繼續向左移動兩位,將sherylann移出參數列表
    /> echo $*
    mark
    /> shift 2                                 #繼續向左移動兩位,由於參數列表中只有mark了,因此本次移動失敗。
    /> echo $*
    mark

    /> cat > test4.sh
    while (( $# > 0 ))                    #等同於 [ $# -gt 0 ]
    do
        echo $*
        shift
    done
    CTRL+D
    /> . ./test4.sh a b c d e
    a b c d e
    b c d e
    c d e
    d e
    e        

    break命令聲明格式:break [n]
    
C語言不同的是,Shellbreak命令攜帶一個參數,即可以指定退出循環的層數。如果沒有指定,其行爲和C語言一樣,即退出最內層循環。如果指定循環的層數,則退出指定層數的循環體。如果有3層嵌套循環,其中最外層的爲1,中間的爲2,最裏面的是3
    
見如下示例腳本:
    /> cat > test5.sh
    while true
    do
        echo -n "Are you ready to move on?"
        read answer
        if [[ $answer == [Yy] ]]
        then
            break
        else
            echo "Come on."
        fi
    done
    echo "Here we are."
    CTRL+D
    /> . ./test5.sh
    Are you ready to move on?
 y
    Here we are

    continue命令聲明格式:continue [n]
    
C語言不同的是,Shellcontinue命令攜帶一個參數,即可以跳轉到指定層級的循環頂部。如果沒有指定,其行爲和C語言一樣,即跳轉到最內層循環的頂部。如果指定循環的層數,則跳轉到指定層級循環的頂部。如果有3層嵌套循環,其中最外層的爲3,中間的爲2,最裏面的是1
    /> cat  maillist                       #測試數據文件maillist的內容爲以下信息。
    stephen
    ann
    sheryl
    mark

    /> cat > test6.sh
    for name in $(cat maillist)
    do
        if [[ $name == stephen ]]; then
            continue
        else
            echo "Hello, $name."
        fi
    done
    CTRL+D
    /> . ./test6.sh
    Hello, ann.
    Hello, sheryl.
    Hello, mark.

    I/O重新定向和子Shell
    
文件中的輸入可以通過管道重新定向給一個循環,輸出也可以通過管道重新定向給一個文件。Shell啓動一個子Shell來處理I/O重新定向和管道。在循環終止時,循環內部定義的任何變量對於腳本的其他部分來說都是不看見的。
    /> cat > demodata                        #爲下面的腳本構造冊數數據
    abc
    def
    ghi
    CRTL+D
    /> cat > test7.sh
    if (( $# < 1 ))                                #如果腳本參數的數量小於1,則給出錯誤提示後退出。
    then
        echo "Usage: $0 filename " >&2
        exit 1
    fi
    count=1
    cat $1 | while read line                   #參數一中的文件被cat命令輸出後,通過管道逐行輸出給while read line
    do
        let $((count == 1)) && echo "Processing file $1..." > /dev/tty  #該行的echo將輸出到當前終端窗口。
        echo -e "$count\t$line"              #將輸出行號和文件中該行的內容,中間用製表符隔開。
        let count+=1
    done > outfile                               #while循環中所有的輸出,除了>/dev/tty之外,其它的全部輸出到outfile文件。
    CTRL+D
    /> . ./test7.sh demodata                #只有一行輸出,其餘的都輸出到outfile中了。
    Processing file demodata...
    /> cat outfile
    1       abc
    2       def
    3       ghi

    /> cat > test8.sh
    for i in 9 7 2 3 5 4
    do
        echo $i
    done | sort -n                                #直接將echo的輸出通過管道重定向sort命令。
    CTRL+D
    /> . ./test8.sh
    2
    3
    4
    5
    7
    9

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章