在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Linux/ 流程控制:for 循環(huán)
網(wǎng)絡(luò)系統(tǒng)
打印
重定向
使用命令
位置參數(shù)
權(quán)限
文本處理
疑難排解
layout: book-zh title: 自定制 shell 提示符
查找文件
layout: book-zh title: vi 簡(jiǎn)介
shell 環(huán)境
什么是 shell
編譯程序
鍵盤(pán)高級(jí)操作技巧
流程控制:case 分支
流程控制:if 分支結(jié)構(gòu)
layout: book-zh title: 軟件包管理
進(jìn)程
存儲(chǔ)媒介
格式化輸出
編寫(xiě)第一個(gè) Shell 腳本
啟動(dòng)一個(gè)項(xiàng)目
流程控制:while/until 循環(huán)
文件系統(tǒng)中跳轉(zhuǎn)
字符串和數(shù)字
讀取鍵盤(pán)輸入
歸檔和備份
探究操作系統(tǒng)
流程控制:for 循環(huán)
自頂向下設(shè)計(jì)
數(shù)組
操作文件和目錄
奇珍異寶
從 shell 眼中看世界
正則表達(dá)式

流程控制:for 循環(huán)

在這關(guān)于流程控制的最后一章中,我們將看看另一種 shell 循環(huán)構(gòu)造。for 循環(huán)不同于 while 和 until 循環(huán),因?yàn)?在循環(huán)中,它提供了一種處理序列的方式。這證明在編程時(shí)非常有用。因此在 bash 腳本中,for 循環(huán)是非常流行的構(gòu)造。

實(shí)現(xiàn)一個(gè) for 循環(huán),很自然的,要用 for 命令。在現(xiàn)代版的 bash 中,有兩種可用的 for 循環(huán)格式。

for: 傳統(tǒng) shell 格式

原來(lái)的 for 命令語(yǔ)法是:

for variable [in words]; do
    commands
done

這里的 variable 是一個(gè)變量的名字,這個(gè)變量在循環(huán)執(zhí)行期間會(huì)增加,words 是一個(gè)可選的條目列表, 其值會(huì)按順序賦值給 variable,commands 是在每次循環(huán)迭代中要執(zhí)行的命令。

在命令行中 for 命令是很有用的。我們可以很容易的說(shuō)明它是如何工作的:

[me@linuxbox ~]$ for i in A B C D; do echo $i; done
A
B
C
D

在這個(gè)例子中,for 循環(huán)有一個(gè)四個(gè)單詞的列表:“A”,“B”,“C”,和 “D”。由于這四個(gè)單詞的列表,for 循環(huán)會(huì)執(zhí)行四次。 每次循環(huán)執(zhí)行的時(shí)候,就會(huì)有一個(gè)單詞賦值給變量 i。在循環(huán)體內(nèi),我們有一個(gè) echo 命令會(huì)顯示 i 變量的值,來(lái)演示賦值結(jié)果。 正如 while 和 until 循環(huán),done 關(guān)鍵字會(huì)關(guān)閉循環(huán)。

for 命令真正強(qiáng)大的功能是我們可以通過(guò)許多有趣的方式創(chuàng)建 words 列表。例如,通過(guò)花括號(hào)展開(kāi):

[me@linuxbox ~]$ for i in {A..D}; do echo $i; done
A
B
C
D

或者路徑名展開(kāi):

[me@linuxbox ~]$ for i in distros*.txt; do echo $i; done
distros-by-date.txt
distros-dates.txt
distros-key-names.txt
distros-key-vernums.txt
distros-names.txt
distros.txt
distros-vernums.txt
distros-versions.txt

或者命令替換:

#!/bin/bash
# longest-word : find longest string in a file
while [[ -n $1 ]]; do
    if [[ -r $1 ]]; then
        max_word=
        max_len=0
        for i in $(strings $1); do
            len=$(echo $i | wc -c)
            if (( len > max_len )); then
                max_len=$len
                max_word=$i
            fi
        done
        echo "$1: '$max_word' ($max_len characters)"
    fi
    shift
done

在這個(gè)示例中,我們要在一個(gè)文件中查找最長(zhǎng)的字符串。當(dāng)在命令行中給出一個(gè)或多個(gè)文件名的時(shí)候, 該程序會(huì)使用 strings 程序(其包含在 GNU binutils 包中),為每一個(gè)文件產(chǎn)生一個(gè)可讀的文本格式的 “words” 列表。 然后這個(gè) for 循環(huán)依次處理每個(gè)單詞,判斷當(dāng)前這個(gè)單詞是否為目前為止找到的最長(zhǎng)的一個(gè)。當(dāng)循環(huán)結(jié)束的時(shí)候,顯示出最長(zhǎng)的單詞。

如果省略掉 for 命令的可選項(xiàng) words 部分,for 命令會(huì)默認(rèn)處理位置參數(shù)。 我們將修改 longest-word 腳本,來(lái)使用這種方式:

#!/bin/bash
# longest-word2 : find longest string in a file
for i; do
    if [[ -r $i ]]; then
        max_word=
        max_len=0
        for j in $(strings $i); do
            len=$(echo $j | wc -c)
            if (( len > max_len )); then
                max_len=$len
                max_word=$j
            fi
        done
        echo "$i: '$max_word' ($max_len characters)"
    fi
done

正如我們所看到的,我們已經(jīng)更改了最外圍的循環(huán),用 for 循環(huán)來(lái)代替 while 循環(huán)。通過(guò)省略 for 命令的 words 列表, 用位置參數(shù)替而代之。在循環(huán)體內(nèi),之前的變量 i 已經(jīng)改為變量 j。同時(shí) shift 命令也被淘汰掉了。

為什么是 i?

你可能已經(jīng)注意到上面所列舉的 for 循環(huán)的實(shí)例都選擇 i 作為變量。為什么呢? 實(shí)際上沒(méi)有具體原因,除了傳統(tǒng)習(xí)慣。 for 循環(huán)使用的變量可以是任意有效的變量,但是 i 是最常用的一個(gè),其次是 j 和 k。

這一傳統(tǒng)的基礎(chǔ)源于 Fortran 編程語(yǔ)言。在 Fortran 語(yǔ)言中,以字母 I,J,K,L 和 M 開(kāi)頭的未聲明變量的類型 自動(dòng)設(shè)為整形,而以其它字母開(kāi)頭的變量則為實(shí)數(shù)類型(帶有小數(shù)的數(shù)字)。這種行為導(dǎo)致程序員使用變量 I,J,和 K 作為循環(huán)變量, 因?yàn)楫?dāng)需要一個(gè)臨時(shí)變量(正如循環(huán)變量)的時(shí)候,使用它們工作量比較少。這也引出了如下基于 fortran 的俏皮話:

“神是真實(shí)的,除非是聲明的整數(shù)?!?/p>

for: C 語(yǔ)言格式

最新版本的 bash 已經(jīng)添加了第二種格式的 for 命令語(yǔ)法,該語(yǔ)法相似于 C 語(yǔ)言中的 for 語(yǔ)法格式。 其它許多編程語(yǔ)言也支持這種格式:

for (( expression1; expression2; expression3 )); do
    commands
done

這里的 expression1,expression2,和 expression3 都是算術(shù)表達(dá)式,commands 是每次循環(huán)迭代時(shí)要執(zhí)行的命令。 在行為方面,這相當(dāng)于以下構(gòu)造形式:

(( expression1 ))
while (( expression2 )); do
    commands
    (( expression3 ))
done

expression1 用來(lái)初始化循環(huán)條件,expression2 用來(lái)決定循環(huán)結(jié)束的時(shí)間,還有在每次循環(huán)迭代的末尾會(huì)執(zhí)行 expression3。

這里是一個(gè)典型應(yīng)用:

#!/bin/bash
# simple_counter : demo of C style for command
for (( i=0; i<5; i=i+1 )); do
    echo $i
done

腳本執(zhí)行之后,產(chǎn)生如下輸出:

[me@linuxbox ~]$ simple_counter
0
1
2
3
4

在這個(gè)示例中,expression1 初始化變量 i 的值為0,expression2 允許循環(huán)繼續(xù)執(zhí)行只要變量 i 的值小于5, 還有每次循環(huán)迭代時(shí),expression3 會(huì)把變量 i 的值加1。

C 語(yǔ)言格式的 for 循環(huán)對(duì)于需要一個(gè)數(shù)字序列的情況是很有用處的。我們將在接下來(lái)的兩章中看到幾個(gè)這樣的應(yīng)用實(shí)例。

總結(jié)

學(xué)習(xí)了 for 命令的知識(shí),現(xiàn)在我們將對(duì)我們的 sys_info_page 腳本做最后的改進(jìn)。 目前,這個(gè) report_home_space 函數(shù)看起來(lái)像這樣:

report_home_space () {
    if [[ $(id -u) -eq 0 ]]; then
        cat <<- _EOF_
        <H2>Home Space Utilization (All Users)</H2>
        <PRE>$(du -sh /home/*)</PRE>
        _EOF_
    else
        cat <<- _EOF_
        <H2>Home Space Utilization ($USER)</H2>
        <PRE>$(du -sh $HOME)</PRE>
        _EOF_
    fi
    return
}

下一步,我們將重寫(xiě)它,以便提供每個(gè)用戶家目錄的更詳盡信息,并且包含用戶家目錄中文件和目錄的總個(gè)數(shù):

report_home_space () {
    local format="%8s%10s%10s\n"
    local i dir_list total_files total_dirs total_size user_name
    if [[ $(id -u) -eq 0 ]]; then
        dir_list=/home/*
        user_name="All Users"
    else
        dir_list=$HOME
        user_name=$USER
    fi
    echo "<H2>Home Space Utilization ($user_name)</H2>"
    for i in $dir_list; do
        total_files=$(find $i -type f | wc -l)
        total_dirs=$(find $i -type d | wc -l)
        total_size=$(du -sh $i | cut -f 1)
        echo "<H3>$i</H3>"
        echo "<PRE>"
        printf "$format" "Dirs" "Files" "Size"
        printf "$format" "----" "-----" "----"
        printf "$format" $total_dirs $total_files $total_size
        echo "</PRE>"
    done
    return
}

這次重寫(xiě)應(yīng)用了目前為止我們學(xué)過(guò)的許多知識(shí)。我們?nèi)匀粶y(cè)試超級(jí)用戶(superuser),但是我們?cè)?if 語(yǔ)句塊內(nèi) 設(shè)置了一些隨后會(huì)在 for 循環(huán)中用到的變量,來(lái)取代在 if 語(yǔ)句塊內(nèi)執(zhí)行完備的動(dòng)作集合。我們添加了給 函數(shù)添加了幾個(gè)本地變量,并且使用 printf 來(lái)格式化輸出。

拓展閱讀