這篇文章主要介紹怎么用Bash編程實現循環,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
成都做網站、網站設計、外貿營銷網站建設,成都做網站公司-創新互聯建站已向成百上千家企業提供了,網站設計,網站制作,網絡營銷等服務!設計與技術結合,多年網站推廣經驗,合理的價格為您打造企業品質網站。
我使用過的所有編程語言都至少有兩種循環結構來用來執行重復的操作。我經常使用 for
循環,然而我發現 while
和 until
循環也很有用處。
我的理解是,在 bash 中實現的 for
命令比大部分語言靈活,因為它可以處理非數字的值;與之形成對比的是,諸如標準 C 語言的 for
循環只能處理數字類型的值。
Bash 版的 for
命令基本的結構很簡單:
for Var in list1 ; do list2 ; done
解釋一下:“對于 list1
中的每一個值,把 $Var
設置為那個值,使用該值執行 list2
中的程序語句;list1
中的值都執行完后,整個循環結束,退出循環。” list1
中的值可以是一個簡單的顯式字符串值,也可以是一個命令執行后的結果(`` 包含其內的命令執行的結果,本系列第二篇文章中有描述)。我經常使用這種結構。
要測試它,確認 ~/testdir
仍然是當前的工作目錄(PWD)。刪除目錄下所有東西,來看下這個顯式寫出值列表的 for
循環的簡單的示例。這個列表混合了字母和數字 — 但是不要忘了,在 bash 中所有的變量都是字符串或者可以被當成字符串來處理。
[student@studentvm1 testdir]$ rm *[student@studentvm1 testdir]$ for I in a b c d 1 2 3 4 ; do echo $I ; doneabcd1234
給變量賦予更有意義的名字,變成前面版本的進階版:
[student@studentvm1 testdir]$ for Dept in "Human Resources" Sales Finance "Information Technology" Engineering Administration Research ; do echo "Department $Dept" ; doneDepartment Human ResourcesDepartment SalesDepartment FinanceDepartment Information TechnologyDepartment EngineeringDepartment AdministrationDepartment Research
創建幾個目錄(創建時顯示一些處理信息):
[student@studentvm1 testdir]$ for Dept in "Human Resources" Sales Finance "Information Technology" Engineering Administration Research ; do echo "Working on Department $Dept" ; mkdir "$Dept" ; doneWorking on Department Human ResourcesWorking on Department SalesWorking on Department FinanceWorking on Department Information TechnologyWorking on Department EngineeringWorking on Department AdministrationWorking on Department Research[student@studentvm1 testdir]$ lltotal 28drwxrwxr-x 2 student student 4096 Apr 8 15:45 Administrationdrwxrwxr-x 2 student student 4096 Apr 8 15:45 Engineeringdrwxrwxr-x 2 student student 4096 Apr 8 15:45 Financedrwxrwxr-x 2 student student 4096 Apr 8 15:45 'Human Resources'drwxrwxr-x 2 student student 4096 Apr 8 15:45 'Information Technology'drwxrwxr-x 2 student student 4096 Apr 8 15:45 Researchdrwxrwxr-x 2 student student 4096 Apr 8 15:45 Sales
在 mkdir
語句中 $Dept
變量必須用引號包裹起來;否則名字中間有空格(如 Information Technology
)會被當做兩個獨立的目錄處理。我一直信奉的一條實踐規則:所有的文件和目錄都應該為一個單詞(中間沒有空格)。雖然大部分現代的操作系統可以處理名字中間有空格的情況,但是系統管理員需要花費額外的精力去確保腳本和 CLI 程序能正確處理這些特例。(即使它們很煩人,也務必考慮它們,因為你永遠不知道將擁有哪些文件。)
再次刪除 ~/testdir
下的所有東西 — 再運行一次下面的命令:
[student@studentvm1 testdir]$ rm -rf * ; lltotal 0[student@studentvm1 testdir]$ for Dept in Human-Resources Sales Finance Information-Technology Engineering Administration Research ; do echo "Working on Department $Dept" ; mkdir "$Dept" ; doneWorking on Department Human-ResourcesWorking on Department SalesWorking on Department FinanceWorking on Department Information-TechnologyWorking on Department EngineeringWorking on Department AdministrationWorking on Department Research[student@studentvm1 testdir]$ lltotal 28drwxrwxr-x 2 student student 4096 Apr 8 15:52 Administrationdrwxrwxr-x 2 student student 4096 Apr 8 15:52 Engineeringdrwxrwxr-x 2 student student 4096 Apr 8 15:52 Financedrwxrwxr-x 2 student student 4096 Apr 8 15:52 Human-Resourcesdrwxrwxr-x 2 student student 4096 Apr 8 15:52 Information-Technologydrwxrwxr-x 2 student student 4096 Apr 8 15:52 Researchdrwxrwxr-x 2 student student 4096 Apr 8 15:52 Sales
假設現在有個需求,需要列出一臺 Linux 機器上所有的 RPM 包并對每個包附上簡短的描述。我為北卡羅來納州工作的時候,曾經遇到過這種需求。由于當時開源尚未得到州政府的“批準”,而且我只在臺式機上使用 Linux,對技術一竅不通的老板(PHB)需要我列出我計算機上安裝的所有軟件,以便他們可以“批準”一個特例。
你怎么實現它?有一種方法是,已知 rpm –qa
命令提供了 RPM 包的完整描述,包括了白癡老板想要的東西:軟件名稱和概要描述。
讓我們一步步執行出最后的結果。首先,列出所有的 RPM 包:
[student@studentvm1 testdir]$ rpm -qaperl-HTTP-Message-6.18-3.fc29.noarchperl-IO-1.39-427.fc29.x86_64perl-Math-Complex-1.59-429.fc29.noarchlua-5.3.5-2.fc29.x86_64java-11-openjdk-headless-11.0.ea.28-2.fc29.x86_64util-linux-2.32.1-1.fc29.x86_64libreport-fedora-2.9.7-1.fc29.x86_64rpcbind-1.2.5-0.fc29.x86_64libsss_sudo-2.0.0-5.fc29.x86_64libfontenc-1.1.3-9.fc29.x86_64<snip>
用 sort
和 uniq
命令對列表進行排序和打印去重后的結果(有些已安裝的 RPM 包具有相同的名字):
[student@studentvm1 testdir]$ rpm -qa | sort | uniqa2ps-4.14-39.fc29.x86_64aajohan-comfortaa-fonts-3.001-3.fc29.noarchabattis-cantarell-fonts-0.111-1.fc29.noarchabiword-3.0.2-13.fc29.x86_64abrt-2.11.0-1.fc29.x86_64abrt-addon-ccpp-2.11.0-1.fc29.x86_64abrt-addon-coredump-helper-2.11.0-1.fc29.x86_64abrt-addon-kerneloops-2.11.0-1.fc29.x86_64abrt-addon-pstoreoops-2.11.0-1.fc29.x86_64abrt-addon-vmcore-2.11.0-1.fc29.x86_64<snip>
以上命令得到了想要的 RPM 列表,因此你可以把這個列表作為一個循環的輸入信息,循環最終會打印每個 RPM 包的詳細信息:
[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done
這段代碼產出了多余的信息。當循環結束后,下一步就是提取出白癡老板需要的信息。因此,添加一個 egrep
命令用來搜索匹配 ^Name
或 ^Summary
的行。脫字符(^
)表示行首,整個命令表示顯示所有以 Name 或 Summary 開頭的行。
[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done | egrep -i "^Name|^Summary"Name : a2psSummary : Converts text and other types of files to PostScriptName : aajohan-comfortaa-fontsSummary : Modern style true type fontName : abattis-cantarell-fontsSummary : Humanist sans serif fontName : abiwordSummary : Word processing programName : abrtSummary : Automatic bug detection and reporting tool<snip>
在上面的命令中你可以試試用 grep
代替 egrep
,你會發現用 grep
不能得到正確的結果。你也可以通過管道把命令結果用 less
過濾器來查看。最終命令像這樣:
[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done | egrep -i "^Name|^Summary" > RPM-summary.txt
這個命令行程序用到了管道、重定向和 for
循環,這些全都在一行中。它把你的 CLI 程序的結果重定向到了一個文件,這個文件可以在郵件中使用或在其他地方作為輸入使用。
這個一次一步構建程序的過程讓你能看到每步的結果,以此來確保整個程序以你期望的流程進行且輸出你想要的結果。
白癡老板最終收到了超過 1900 個不同的 RPM 包的清單,我嚴重懷疑根本就沒人讀過這個列表。我給了他們想要的東西,沒有從他們嘴里聽到過任何關于 RPM 包的信息。
Bash 中還有兩種其他類型的循環結構:while
和 until
結構,兩者在語法和功能上都類似。這些循環結構的基礎語法很簡單:
while [ expression ] ; do list ; done
邏輯解釋:表達式(expression
)結果為 true 時,執行程序語句 list
。表達式結果為 false 時,退出循環。
until [ expression ] ; do list ; done
邏輯解釋:執行程序語句 list
,直到表達式的結果為 true。當表達式結果為 true 時,退出循環。
while
循環用于當邏輯表達式結果為 true 時執行一系列程序語句。假設你的 PWD 仍是 ~/testdir
。
最簡單的 while
循環形式是這個會一直運行下去的循環。下面格式的條件語句永遠以 true
作為返回。你也可以用簡單的 1
代替 true
,結果一樣,但是這解釋了 true 表達式的用法。
[student@studentvm1 testdir]$ X=0 ; while [ true ] ; do echo $X ; X=$((X+1)) ; done | head0123456789[student@studentvm1 testdir]$
既然你已經學了 CLI 的各部分知識,那就讓它變得更有用處。首先,為了防止變量 $X
在前面的程序或 CLI 命令執行后有遺留的值,設置 $X
的值為 0。然后,因為邏輯表達式 [ true ]
的結果永遠是 1,即 true,在 do
和 done
中間的程序指令列表會一直執行 — 或者直到你按下 Ctrl+C
抑或發送一個 2 號信號給程序。那些程序指令是算數擴展,用來打印變量 $X
當前的值并加 1.
《系統管理員的 Linux 哲學》的信條之一是追求優雅,實現優雅的一種方式就是簡化。你可以用操作符 ++
來簡化這個程序。在第一個例子中,變量當前的值被打印出來,然后變量的值增加了。可以在變量后加一個 ++
來表示這個邏輯:
[student@studentvm1 ~]$ X=0 ; while [ true ] ; do echo $((X++)) ; done | head0123456789
現在刪掉程序最后的 | head
再運行一次。
在下面這個版本中,變量在值被打印之前就自增了。這是通過在變量之前添加 ++
操作符實現的。你能看出區別嗎?
[student@studentvm1 ~]$ X=0 ; while [ true ] ; do echo $((++X)) ; done | head123456789
你已經把打印變量的值和自增簡化到了一條語句。類似 ++
操作符,也有 --
操作符。
你需要一個在循環到某個特定數字時終止循環的方法。把 true 表達式換成一個數字比較表達式來實現它。這里有一個循環到 5 終止的程序。在下面的示例代碼中,你可以看到 -le
是 “小于或等于” 的數字邏輯操作符。整個語句的意思:只要 $X
的值小于或等于 5,循環就一直運行。當 $X
增加到 6 時,循環終止。
[student@studentvm1 ~]$ X=0 ; while [ $X -le 5 ] ; do echo $((X++)) ; done012345[student@studentvm1 ~]$
until
命令非常像 while
命令。不同之處是,它直到邏輯表達式的值是 true
之前,會一直循環。看一下這種結構最簡單的格式:
[student@studentvm1 ~]$ X=0 ; until false ; do echo $((X++)) ; done | head0123456789[student@studentvm1 ~]$
它用一個邏輯比較表達式來計數到一個特定的值:
[student@studentvm1 ~]$ X=0 ; until [ $X -eq 5 ] ; do echo $((X++)) ; done01234[student@studentvm1 ~]$ X=0 ; until [ $X -eq 5 ] ; do echo $((++X)) ; done12345[student@studentvm1 ~]$
以上是“怎么用Bash編程實現循環”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注創新互聯行業資訊頻道!
網站題目:怎么用Bash編程實現循環
網頁網址:http://vcdvsql.cn/article42/phodec.html
成都網站建設公司_創新互聯,為您提供Google、、用戶體驗、建站公司、關鍵詞優化、云服務器
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯