濮阳杆衣贸易有限公司

主頁 > 知識庫 > Linux折騰記(十):Bash腳本編程語言中的美學(xué)與哲學(xué)

Linux折騰記(十):Bash腳本編程語言中的美學(xué)與哲學(xué)

熱門標(biāo)簽:新鄭電銷外呼系統(tǒng)線路 樺甸電銷機器人 河北語音電銷機器人 商戶地圖標(biāo)注 電話機器人哪里有賣的 地球地圖標(biāo)注方法 怎樣給景區(qū)加百度地圖標(biāo)注 河南智能電話機器人公司 壽光百度地圖標(biāo)注中心網(wǎng)站

  我承認(rèn),我再一次地當(dāng)了標(biāo)題黨。但是不可否認(rèn),這一定是一篇精華隨筆。在這一篇中,我將探討B(tài)ash腳本語言中的美學(xué)與哲學(xué)。 這不是一篇Bash腳本編程的教程,但是卻能讓人更加深入地了解Bash腳本編程,更加快速地學(xué)習(xí)Bash腳本編程。 閱讀這篇隨筆,不需要你有Bash編程的經(jīng)驗,但一定要和我一樣熱衷于探索各種編程語言的本質(zhì),感悟它們的魅力。

  其實早就想寫關(guān)于Bash的東西了。 我們平時喜歡對編程語言進(jìn)行分類,比如面向過程的編程語言、面向?qū)ο蟮木幊陶Z言、函數(shù)式編程語言等等。在我心中,我認(rèn)為Bash就是一個面向字符串的編程語言。Bash腳本語言的本質(zhì):一切皆是字符串。 Bash腳本語言的一切哲學(xué)都圍繞著字符串:它們從哪里來?到哪里去?使命是什么? Bash腳本語言的一切美學(xué)都源自字符串: 由鍵盤上幾乎所有的符號 “$ ~ ! # ( ) [ ] { } | > - . , ; * @ ' " ` \ ^” 排列組合而成的極富視覺沖擊力的、功能極其復(fù)雜的字符串。

一、一切皆是字符串

  Bash是一個Shell,Shell出現(xiàn)的初衷是為了將系統(tǒng)中的各種工具粘合在一起,所以它最根本的功能是調(diào)用各種命令。 但是Bash又提供了豐富的編程功能。 我們經(jīng)常對編程語言進(jìn)行分類,比如面向過程的語言、面向?qū)ο蟮恼Z言、面向函數(shù)的語言等等。 可以把Bash腳本語言看成是一個面向字符串的語言。 Bash語言的本質(zhì)就是:一切都是字符串。 看看下圖中的這些變量:

  上圖是我在交互式的Bash命令行中做的一些演示。在上圖中,我對變量分別賦值,不管等號右邊是一個沒有引號的字符串,還是帶有引號的字符串,甚至數(shù)字,或者數(shù)學(xué)表達(dá)式,最終的結(jié)果,變量里面存儲的都是字符串。我使用一個for循環(huán)顯示所有的變量,可以看到數(shù)學(xué)表達(dá)式也只是以字符串的形式儲存,沒有被求值。

二、引用和元字符

  如果一切都是沒有特殊功能的平凡的字符串,那就無法構(gòu)成一門編程語言。在Bash中,有很多符號具有特殊含義,比如“$”符號被用于字符串展開,“”符號用于讓命令在后臺執(zhí)行, “|”用作管道, “>” “”用于輸入輸出重定向等等。所以在Bash中,雖然同樣是字符串,但是被引號包圍的字符串和不被引號包圍的字符串使用起來是不一樣的,被單引號包圍的字符串和被雙引號包圍起來的字符串也是不一樣的。

  究竟帶引號的字符串和不帶引號的字符串使用起來有什么不一樣呢?下圖是我構(gòu)建的一些比較典型的例子:

  在上圖中,我展示了Bash中生成字符串的7種方法:大括號展開、波浪符展開、參數(shù)展開、命令替換、算術(shù)展開、單詞分割和文件路徑展開。還有兩種生成字符串的方式?jīng)]有講(Process substitution和歷史命令展開)。在使用Bash腳本編程的時候,了解以上7種字符串生成的方式就夠了。在交互式使用Bash命令行的時候,還需要了解歷史命令展開,熟練使用歷史命令展開可以讓人事半功倍。

  在上面的圖片中可以看到,有一些展開方式在被雙引號包圍的字符串中是不起作用的,比如大括號展開、波浪符展開、單詞分割、文件路徑展開,而只有參數(shù)展開、命令替換和算術(shù)展開是起作用的。從圖片中還可以看出,字符串中的參數(shù)展開、命令替換和算術(shù)展開都是由“$”符號引導(dǎo),命令替換還可以由“`”引導(dǎo)。所以,可以進(jìn)一步總結(jié)為,在雙引號包圍的字符串中,只有“$、`、\&;這三個字符具有特殊含義。

  如果想讓任何一個字符都不具有特殊含義,可以使用單引號將字符串包圍。比如使用正則表達(dá)式的時候,還比如使用sed、awk等工具的時候,由于sed和awk自己執(zhí)行的命令中往往包含有很多特殊字符,所以它們的命令最好用單引號包圍。 比如使用awk命令顯示/etc/passwd文件中的每個用戶的用戶名和全名,可以使用這個命令 awk -e '{print $1,$5}' ,其中,傳遞給awk的命令用單引號包圍,說明bash不執(zhí)行其中的任何替換或展開。

  另外一個特殊的字符是“\&;,它也是引用的一種。它可以解除緊跟在它后面的一個特殊字符的特殊含義(引用)。之所以需要“\&;的存在,是因為在Bash中,有些字符稱為元字符,這些字符一旦出現(xiàn),就會將一個字符串分割為多個子串。如果需要在一個字符串中包含這些元字符本身,就必須對它們進(jìn)行引用。如下圖:

  最常見的元字符就是空格。 從上面幾張圖片可以看出,如果要將一個含有空格的字符串賦值給一個變量,要么把這個字符串用雙引號包圍,要么使用“\&;對空格進(jìn)行引用。 從上圖中可以看出,Bash中只有9個元字符,它們分別是“| ( ) ; > space tab”,而在其它編程語言中經(jīng)常出現(xiàn)的元字符“. { } [ ]”以及作為數(shù)學(xué)運算的加減乘除,在Bash中都不是元字符。

三、字符串從哪里來、到哪里去

  介紹完字符串、介紹完引用和元字符,下一個目標(biāo)就是來探討這一個哲學(xué)問題:字符串從哪里來、到哪里去?通過該哲學(xué)問題的探討,可以推導(dǎo)出Bash腳本語言的整個語法。字符串從哪里來?很顯然,其中一個很直接的來源就是我們從鍵盤上敲上去的。除此之外,就是我前面提到的七八九種字符串展開的方法了。

  字符串展開的流程如下:

    1.先用元字符將一個字符串分割為多個子串;

    2.如果字符串是用來給變量賦值,則不管它是否被雙引號包圍,都認(rèn)為它被雙引號包圍;

    3.如果字符串不被單引號和雙引號包圍,則進(jìn)行大括號展開,即將{a,b}c展開為ab ac;

以上三個流程可以通過下圖證明:

    4.如果字符串不被單引號或雙引號包圍,則進(jìn)行波浪符展開,即將~/展開為用戶的主目錄,將~+/展開為當(dāng)前工作目錄(PWD),將~-/展開為上一個工作目錄(OLDPWD);

    5.如果字符串不被單引號包圍,則進(jìn)行參數(shù)和變量展開;這一類的展開全都以“$”開頭,這是整個Bash字符串展開中最復(fù)雜的,其中包括用戶定義的變量,包括所有的環(huán)境變量,以上兩種展開方式都是“$”后跟變量名,還包括位置變量“$1、 $2、 ...、 $9、 ... ”,其它特殊變量:“$@、 $*、 $#、 $-、 $!、 $0、 $?、 $_ ”,甚至還有數(shù)組:“${var[i]}”, 還可以在展開的過程中對字符串進(jìn)行各種復(fù)雜的操作,如:“ ${parameter:-word}、 ${parameter:=word}、 ${parameter:+word}、 ;${parameter:?word}、 ${parameter:offset}、 ${parameter:offset:length}、 ${!prefix*}、 ${!prefix@}、 ${name[@]}、 ${!name[*]}、 ${#parameter}、 ${parameter#word}、 ${parameter##word}、 ${parameter%word}、 ${parameter%%word}、 ${parameter/pattern/string}、 ${parameter^pattern}、 ${parameter^^pattern}、 ${parameter,pattern}、 ${parameter,,pattern}”;

    6.如果字符串不被單引號包圍,則進(jìn)行命令替換;命令替換有兩種格式,一種是$(...),一種是`...`;也就是將命令的輸出作為字符串的內(nèi)容;

    7.如果字符串不被單引號包圍,則進(jìn)行算術(shù)展開;算術(shù)展開的格式為$((...));

    8.如果字符串不被單引號或雙引號包圍,則進(jìn)行單詞分割;

    9.如果字符串不被單引號或雙引號包圍,則進(jìn)行文件路徑展開;

    10.以上流程全部完成后,最后去掉字符串外面的引號(如果有的話)。以上流程只按以上順序進(jìn)行一遍。比如不會在變量展開后再進(jìn)行大括號展開,更不會在第10步去除引用后執(zhí)行前面的任何一步。如果需要將流程再走一遍,請使用eval。

  探討完了字符串從哪里來,下面來看看字符串到哪里去。也就是怎么使用這些字符串。使用字符串有以下幾種方式:

    1.把它當(dāng)命令執(zhí)行;這是Bash中的最根本的用法,畢竟Shell的存在就是為了粘合各種命令。如果一個字符串出現(xiàn)在本該命令出現(xiàn)的地方(比如一行的開頭,或者關(guān)鍵字then、do等的后面),它將會被當(dāng)成命令執(zhí)行,如果它不是個合法的命令,就會報錯;

    2.把它當(dāng)成表達(dá)式;Bash中本沒有表達(dá)式,但是有了((...))和[[...]],就有了表達(dá)式;((...))可以把它里面的字符串當(dāng)成算術(shù)表達(dá)式,而[[...]]會把它里面的字符串當(dāng)邏輯表達(dá)式,僅此兩個特例;

    3.給變量賦值;這也是一個特例,有點破壞Bash編程語言語法哲學(xué)的完整性。為什么這么說呢?因為“=”即不是一個元字符,也不允許兩邊有空格,而且只有第1個等號會被當(dāng)成賦值運算符。

  下面圖片為以上觀點給出證據(jù):

四、再加上一點點的定義,就可以推導(dǎo)出整個Bash腳本語言的語法了

  前面我已經(jīng)展示了我對字符串從哪里來、到哪里去這個問題的理解。關(guān)于字符串的去向,除了兩個表達(dá)式和一個為變量賦值這三個特例,剩下的就只有當(dāng)命令來執(zhí)行了。在前面,我提到了元字符和引用的概念,這里,還得再增加一點點定義:

    定義1:控制操作符(Control Operator) 前面提到元字符是為了把一個字符串分割為多個子串,而控制操作符就是為了把一系列的字符串分割成多個命令。舉例說明,在Bash中,一個字符串 cat /etc/passwd 就是一個命令,第一個單詞cat是命令,第2個單詞/etc/passwd是命令的參數(shù),而字符串 cat /etc/passwd | grep youxia 就是兩個命令,這兩個命令分別是cat和grep,它們之間通過“|”分割,所以這里的“|”是控制操作符。熟悉Shell的朋友肯定知道“|”代表的是管道,所以它的作用是1.把一個字符串分割為兩個命令,2.將第一個命令的輸出作為第二個命令的輸入。在Bash中,總共只有10個控制操作符,它們分別是“|| | ; ;; ( ) | newline>”。只要看到這些控制操作符,就可以認(rèn)為它前面的字符串是一個完整的命令。

    定義2:關(guān)鍵字(Reserved Words) 我沒有將其翻譯成保留字,很顯然,作為編程語言來說,它們應(yīng)該叫做關(guān)鍵字。一門編程語言肯定必須得提供選擇、循環(huán)等流程控制語句,還得提供定義函數(shù)的功能。這些功能只能通過關(guān)鍵字實現(xiàn)。在Bash中,只有22個關(guān)鍵字,它們是“! case coproc do done elif else esac fi for function if in select then until while { } time [[ ]]”。這其中有不少的特別之處,比如“! { } [[ ]]”等符號都是關(guān)鍵字,也就是說它們當(dāng)關(guān)鍵字使用時相當(dāng)于一個單詞,也就是說它們和別的單詞必須以元字符分開(否則無法成為獨立的單詞)。這也是為什么在Bash中使用“! { } [[ ]]”時經(jīng)常要在它們周圍留空格的原因。(再一次證明“=”是一個很變態(tài)的特例,因為它既不是元字符,也不是控制操作符,更加不是關(guān)鍵字,它到底是什么?)

  下面開始推導(dǎo)Bash腳本語言的語法:

    推導(dǎo)1:簡單命令(Simple command) 就是一條簡單的命令,它可以是一個以上述控制操作符結(jié)尾的字符串。比如單獨放在一行的 uname -r 命令(單獨放在一行的命令其實是以newline>結(jié)尾,newline>是控制操作符),或者雖然不單獨放在一行,但是以“;”或“”結(jié)尾,比如 uname -r; who; pwd; gvim 其中每一個命令都是一個簡單命令(當(dāng)然,這四個命令放在一起的這行代碼不叫簡單命令),“;”就是簡單地分割命令,而“”還有讓命令在后臺執(zhí)行的功能。這里比較特殊的是雙分號“;;”,它只用在case語句中。

    推導(dǎo)2:管道(Pipe Line) 管道是Shell中的精髓,就是讓前一個命令的輸出成為后一個命令的輸入。管道的完整語法是這樣 [time [-p]] [ ! ] command1 | command2 或這樣 [time [-p]] [ ! ] command1 | command2 的。其中time關(guān)鍵字和!關(guān)鍵字都是可選的(使用[...]指出哪些部分是可選的),time關(guān)鍵字可以計算命令運行的時間,而!關(guān)鍵字是將命令的返回狀態(tài)取反??辞宄?關(guān)鍵字周圍的空格哦。如果使用“|”,就是把第一個命令的標(biāo)準(zhǔn)輸出作為第二個命令的標(biāo)準(zhǔn)輸入,如果使用“|”,則將第一個命令的標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤輸出都當(dāng)成第二個命令的輸入。

    推導(dǎo)3:命令序列(List) 如果多個簡單命令或多個管道放在一起,它們之間以“; newline> || ”等控制操作符分開,就稱之為一個命令序列。關(guān)于“; newline>”前面已經(jīng)講過了,無需重復(fù)。關(guān)于“||”和“”,熟悉C、C++、Java等編程語言的朋友們肯定也不會陌生,它們遵循同樣的短路求值的思想。比如 command1 || command2 只有當(dāng)command1執(zhí)行不成功的時候才執(zhí)行command2,而 command1 command2 只有當(dāng)command1執(zhí)行成功的時候才執(zhí)行command2。

    推導(dǎo)4:復(fù)合命令(Compound Commands) 如果將前面的簡單命令、管道或者命令序列以更復(fù)雜的方式組合在一起,就可以構(gòu)成復(fù)合命令。在Bash中,有4種形式的復(fù)合命令,它們分別是 (list) 、  { list; } 、  ((expression)) 、  [[ expression ]] 。請注意第2種形式和第4種形式大括號和中括號周圍的空格,也請注意第2種形式中l(wèi)ist后面的“;”,不過如果“}”另起一行,則不需要“;”,因為newline>和“;”是起同樣作用的。在以上4種復(fù)合命令中, (list) 是在一個新的Shell中執(zhí)行命令序列,這些命令的執(zhí)行不會影響當(dāng)前Shell的環(huán)境變量,而 { list; } 只是簡單地將命令序列分組。后面兩種表達(dá)式求值前面已經(jīng)講過,這里就不講了。后面可能會詳細(xì)列出邏輯表達(dá)式求值的選項。

  上面的4步推導(dǎo)是一步更進(jìn)一步的,是由簡單逐漸到復(fù)雜的,最簡單的命令可以組合成稍復(fù)雜的管道,再組合成更復(fù)雜的命令序列,最后組成最復(fù)雜的復(fù)合命令。

  下面是Bash腳本語言的流程控制語句,如下:

    1. for name [ [ in [ word ... ] ] ; ] do list ; done ;

    2. for (( expr1 ; expr2 ; expr3 )) ; do list ; done ;

    3. select name [ in word ] ; do list ; done ;

    4. case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac ;

    5. if list; then list; [ elif list; then list; ] ... [ else list; ] fi ;

    6. while list-1; do list-2; done ;

    7. until list-1; do list-2; done 。

  上面的公式大家看得懂吧,我相信大家肯定看得懂。其中的[...]代表的是可以有也可以真沒有的部分。在以上公式中,請注意第2個公式for循環(huán)中的雙括號,它執(zhí)行的是其中的表達(dá)式的算術(shù)運算,這是和其它高級語言的for循環(huán)最像的,但是很遺憾,Bash中的算術(shù)表達(dá)式目前只能計算整數(shù)。再請注意第3個公式,select語法,和for...in...循環(huán)的語法比較類似,但是它可以在屏幕上顯示一個菜單。如果我沒有記錯的話,Basic語言中應(yīng)該有這個功能。其它的控制結(jié)構(gòu)在別的高級語言中都很常見,就不需要我在這里啰嗦了。

  最后,再來展示一下如何定義函數(shù):

     name () compound-command [redirection] 

    或者

     function name [()] compound-command [redirection] 

  可以看出,如果有function關(guān)鍵字,則“()”是可選的,如果沒有function關(guān)鍵字,則“()”是必須的。這里需要特別指出的是:函數(shù)體只要求是compound-command,我前面總結(jié)過compound-command有四種形式,所以有時候定義一個函數(shù)并不會出現(xiàn)“{ }”哦。如下圖,這樣的函數(shù)也是合法的:

  That's all。這就是Bash腳本語言的全部語法。就這么簡單。

  好像忘了點什么?對了,還有輸入輸出重定向沒有講。輸入輸出重定向是Shell中又一個偉大的發(fā)明,它的存在有著它獨特的哲學(xué)意義。這個請看下一節(jié)。

五、輸入輸出重定向

  Unix世界有一個偉大的哲學(xué):一切皆是文件。(這個扯得有點遠(yuǎn)。)Unix世界還有一個偉大的哲學(xué):創(chuàng)建進(jìn)程比較方便。(這個扯得也有點遠(yuǎn)。)而且,每一個進(jìn)程一創(chuàng)建,就會自動打開三個文件,它們分別是標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯誤輸出,普通情況下,它們連接到用戶的控制臺。在Shell中,使用數(shù)字來標(biāo)識一個打開的文件,稱為文件描述符,而且數(shù)字0、 1、 2分別代表標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤輸出。在Shell中,可以通過“>”、“”將命令的輸入、輸出進(jìn)行重定向。結(jié)合exec命令,可以非常方便地打開和關(guān)閉文件。需要注意的是,當(dāng)文件描述符出現(xiàn)在“>”、“”右邊的時候,前面要使用“”符號,這可能是為了和數(shù)學(xué)表達(dá)式中的大于和小于進(jìn)行區(qū)別吧。使用“-”可以關(guān)閉文件描述符。

  “> 數(shù)字 exec -”,這就是輸入輸出重定向的全部。下面的公式中,我使用n代表數(shù)字,如果是兩個不同的數(shù)字,則使用n1、n2,使用[...]代表可選參數(shù)。輸入輸出重定向的語法如下:


復(fù)制代碼
代碼如下:

[n]> file #重定向標(biāo)準(zhǔn)輸出(或 n)到file。
[n]>> file #重定向標(biāo)準(zhǔn)輸出(或 n)到file,追加到file末尾。
[n] file #將file重定向到標(biāo)準(zhǔn)輸入(或 n)。
[n1]>n2 #重定向標(biāo)準(zhǔn)輸出(或 n1)到n2。
2> file >2 #重定向標(biāo)準(zhǔn)輸出和錯誤輸出到file。
| command #將標(biāo)準(zhǔn)輸出通過管道傳遞給command。
2>1 | command #將標(biāo)準(zhǔn)輸出和錯誤輸出一起通過管道傳遞給command,等同于|。

  請注意,數(shù)字和“>”、“”符號之間是沒有空格的。結(jié)合exec,可以非常方便地使用一個文件描述符來打開、關(guān)閉文件,如下:


復(fù)制代碼
代碼如下:

echo Hello >file1
exec 3file1 4>file2 #打開文件
cat 3 >4 #重定向標(biāo)準(zhǔn)輸入到 3,標(biāo)準(zhǔn)輸出到 4,相當(dāng)于讀取file1的內(nèi)容然后寫入file2
exec 3- 4>- #關(guān)閉文件
cat file2
#顯示結(jié)果為 Hello/p> p>#還可以暫存和恢復(fù)文件描述符,如下:
exec 5>2 #把原來的標(biāo)準(zhǔn)錯誤輸出保存到文件描述符5上
exec 2> /tmp/$0.log #重定向標(biāo)準(zhǔn)錯誤輸出
...
exec 2>5 #恢復(fù)標(biāo)準(zhǔn)錯誤輸出
exec 5>- #關(guān)閉文件描述符5,因為不需要了

  還可以將“>”一起使用,表示打開一個文件進(jìn)行讀寫。

  除了exec,輸入輸出重定向和read命令配合也很好用,read命令每次讀取文件的一行。但是要注意的是,輸入輸出重定向放到for、while等循環(huán)的循環(huán)體和循環(huán)外,效果是不一樣的。如下圖:

  另外,輸入輸出重定向符號“>”、“”還可以和“()”一起使用,表示進(jìn)程替換(Process substitution),如“>(list)”、“(list)”。結(jié)合前面提到的“”、“>”、“(list)”的含義,進(jìn)程替換的作用是很容易猜到的哦。

六、Bash腳本語言的美學(xué):大道至簡

  如果你問我Bash腳本語言哪里美?我會回答:簡潔就是美。請看下面逐條論述:

  1.使用了簡潔的抽象的符號。Bash腳本語言幾乎使用到了鍵盤上能夠找到的所有符號,比如“$”用作字符串展開,“|”用作管道,“”、“>”用作輸入輸出重定向,一點都不浪費;

  2.只使用了9個元字符、10個控制操作符和22個關(guān)鍵字,就構(gòu)建了一個完整的、面向字符串編程的語言;

  3.概念上具有很好的一致性;比如 (list) 復(fù)合命令的功能是執(zhí)行括號內(nèi)的命令序列,而“$”用于引導(dǎo)字符串展開,所以 $(list) 用于命令替換(所以我前面說“$()”形式的命令替換比“``”形式的命令替換更加具有一致性)。比如 ((expresion)) 用于數(shù)學(xué)表達(dá)式求值,所以 $((expression)) 代表算術(shù)展開。再比如“{}”和“,”配合使用,且中間沒有空格時,代表大括號展開,但是當(dāng)需要使用“{ }”來定義復(fù)合命令時,必須把“{ }”當(dāng)關(guān)鍵字,它們和它里面的內(nèi)容必須以空格隔開,而且“}”和它前面的一條命令之間必須有一個“;”或者“newline>”。這些概念上的一致性設(shè)計得非常精妙,使用起來自然而然可以讓人體會到一種美感;

  4.完美解決了一個命令執(zhí)行時的輸出和運行狀態(tài)的分離。有其它編程語言經(jīng)歷的人也經(jīng)常會遇到這樣的問題:當(dāng)我們調(diào)用一個函數(shù)的時候,函數(shù)可能會產(chǎn)生兩個結(jié)果,一個是函數(shù)的返回值,一個是函數(shù)調(diào)用是否成功。在C#和Java等高級語言中,往往使用try...catch等捕獲異常的方式來判斷函數(shù)調(diào)用是否成功,但仍然有程序員讓函數(shù)返回null代表失敗,而C語言這種沒有異常機制的語言,實在是難以判斷一個函數(shù)的返回值究竟如何表示該函數(shù)調(diào)用是否成功(比如就有很多API讓函數(shù)返回-1代表失敗,而有的函數(shù)運行失敗是會設(shè)置errno全局變量)。在Bash中,命令運行的狀態(tài)和命令的標(biāo)準(zhǔn)輸出區(qū)分很明確,如果你需要命令的標(biāo)準(zhǔn)輸出,使用命令替換來生成字符串,如果你只需要命令的運行狀態(tài),直接將命令寫在if語句之中即可,或者使用$?特殊變量來檢查上一條命令的運行狀態(tài)。如果不想在檢查命令運行狀態(tài)的時候讓命令的標(biāo)準(zhǔn)輸出影響用戶,可以把它重定向到/dev/null,比如


復(fù)制代碼
代碼如下:

if cat /etc/passwd | grep youxia > /dev/null; then echo 'youxia is exist'; fi

  5.使用管道和輸入輸出重定向讓文件的讀寫變得簡單。想一想在C語言中怎么讀文件吧,除了麻煩的open、close不說,每讀一個字符串還得先準(zhǔn)備一個buffer,準(zhǔn)備長了怕浪費空間,準(zhǔn)備短了怕緩沖區(qū)溢出,虐心啦。使用Bash,那真的是太方便了。

  6.它還是一門不折不扣的動態(tài)語言哦,eval命令實在是太強大了,請看下圖,模擬指針進(jìn)行查表:

  當(dāng)然,自從Bash 3之后,Bash本身就提供了間接引用的功能(使用“${!var}”)。

  例外:

    Bash語言也并不是在所有的方面都是完美的,還存在幾個特別的例外。比如前面說的“=”。除了“=”,“()”也有一個使用不一致的地方,那就是對數(shù)組的初始化,比如 array=(a b c d e f) ,這和前面講的“()”用于在子Shell中執(zhí)行命令序列還真的是不一致。

總結(jié):

  以上內(nèi)容是我的胡言亂語,因為以上內(nèi)容即無法教會大家完整的Bash語法,也無法教會大家用Bash做任何一點有意義的工作。

  如果想用Bash干點實事,我送大家一本O'Reilly出的《Shell腳本學(xué)習(xí)指南》

  另外,我的主要參考資料來自于Bash用戶手冊。大家可以在自己的系統(tǒng)中運行 man bash 。

標(biāo)簽:荊州 楚雄 來賓 忻州 阜陽 淄博 迪慶 遼陽

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Linux折騰記(十):Bash腳本編程語言中的美學(xué)與哲學(xué)》,本文關(guān)鍵詞  Linux,折騰,記,十,Bash,腳本,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Linux折騰記(十):Bash腳本編程語言中的美學(xué)與哲學(xué)》相關(guān)的同類信息!
  • 本頁收集關(guān)于Linux折騰記(十):Bash腳本編程語言中的美學(xué)與哲學(xué)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    安国市| 曲周县| 黄浦区| 长沙县| 南京市| 福建省| 永定县| 庆元县| 昌都县| 永善县| 黑河市| 大姚县| 邵武市| 双桥区| 孟村| 汾西县| 顺昌县| 潼南县| 贵阳市| 元谋县| 乳源| 正宁县| 拉萨市| 静宁县| 花莲县| 贡嘎县| 澄江县| 滕州市| 西丰县| 汽车| 蒲城县| 濮阳市| 耒阳市| 文水县| 宜阳县| 房产| 涟源市| 杂多县| 邮箱| 司法| 霍城县|