標籤:使用 strong io 檔案 問題 ar 時間 應用
最近在梳理bash知識的的過程中,有幸閱讀了man bash文檔,一時間猶如醍醐灌頂一般,很多當初不明白的地方都豁然開朗,現在就其中的一點做一分享,同時也為man bash做一下廣告,當你面對bash問題孤立無援的時候,別忘了還有man bash的陪伴。
Bash 支援的擴充種類有:brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, word splitting, and pathname expansion(為了表述精確起見,這裡就直接應用原文中的術語了)。還有一個叫:process substitution
他們的優先順序順序為:brace expansion, tilde expansion, parameter, variable expansion, arithmetic expansion, command substitution , word splitting, pathname expansion
brace expansion
brace值得就是“{ }”。該擴充是用來產生字串的,下面舉兩個例子:
如果括弧中間是“..”,則產生連續字元
tilde expansion
tilde值得就是“~”,我們都清楚~指的是HOME,這裡還有另外兩個,他們是“~+”和“~-”,分別代表PWD和OLDPWD,使用這兩個可以剛方便我們的指令碼編寫,舉個例子:
Parameter expansion
這個是bash中最重要、也是最常用的擴充,但整整瞭解他的人並不多,這裡就來揭開它不為人知的另一面:
它的標準形式為${parameter},簡寫為$parameter,使用${parameter}可以避免很多不必要的麻煩。
${parameter:-word},如果parameter為空白,或者根本沒有定義parameter,則採用預設值,
${parameter:=word},如果parameter為空白,或者根本沒有定義parameter,則賦予預設值
上面兩個的區別在於前者沒有給parameter賦值,舉個例子:
${parameter:?word},如果parameter為空白,或者根本沒有定義parameter,則列印出錯資訊
${parameter:+word},如果parameter取值不為空白,則用word替換
${parameter:offset}
${parameter:offset:length}
上面兩個是用來截取指定長度字串的,截取的下標offset從0開始計數,長度由length指定。如果沒有指定length,則一直截取的末尾:
${!prefix*}
${!prefix@}
這兩個的意思相同,都是擴充成以prefix為開頭的變數名稱,同時會使用IFS的第一個變數把他們分隔開。例如:
${!name[@]}
${!name[*]}
這兩個是用來查詢數組下標的。列印出來的是name數組有哪些下標。注意:這個和${name[@]},${name[*]}不同,這兩個是列印的每個數組元素的內容,而我們這裡在講的這兩個是列印的數組下標。例如:
補充一點,如果你使用了associative array,他會自動取代下標為0的元素。例如:
${#parameter},列印parameter的長度,
${parameter#word},使用pathname expansion把word作為一個pattern來擴充,從頭開始掃描parameter,輸出滿足patter的最短匹配串。
${parameter##word},使用pathname expansion把word作為一個pattern來擴充,從頭開始掃描parameter,輸出滿足patter的最長相符串。
${parameter%word},使用pathname expansion把word作為一個pattern來擴充,從尾開始掃描parameter,輸出滿足patter的最短匹配串。
${parameter%%word},使用pathname expansion把word作為一個pattern來擴充,從尾開始掃描parameter,輸出滿足patter的最長相符串。
${parameter/pattern/string},用string替換parameter中的pattern。從頭掃描,pattern採用的是pathname expansion;替換第一個匹配
${parameter//pattern/string},用string替換parameter中的pattern。從頭掃描,pattern採用的是pathname expansion;替換所有匹配
另外的,如果parameter是數組,那麼數組的每個元素都採取相同的策略,如:
command substitution
很常用的功能,兩種形式:$(command)和`command`,基本使用說,地球人都知道。但是如果要想嵌套怎麼辦呢?看了下面的例子你就明白了:
對了,就是用反斜線轉移來實現嵌套。
arithmetic expansion
形式為:$((expression)),例如:
Process Substitution
這個擴充在開始沒有提到。這個擴充使用了FIFO,所以,他只能在支援FIFO的系統中使用。他的形式為<(command list)或者>(command list)。用到這個擴充的時候,它會在/dev/fd中產生臨時檔案,用來接收command list的輸出,然後,把裡面的內容發送給當前的命令。這個命令在需要臨時儲存某幾個命令的輸出,並把輸出用來後續處理的時候非常有用,可以避免產生過多臨時檔案。例如:
從最後一條命令的輸出可以看得出,這種替換是把中間的結果放到了兩個臨時檔案中,它們是:/dev/fd/63和/dev/fd/62。命令完成後,這兩個檔案就會消失。
Word splitting
顧名思義,就是按照IFS分割輸出,例如:
pathname expansion
就是我們常用的ls ? ls *。? * 的含義大家都清楚。但是這個擴充行為與set和shopt中個多個設定有關,現列舉如下:
noglob -d 禁止用路徑名擴充。即關閉萬用字元。(用set –o可以看到,後面的用shopt可以看到)
dotglob bash在檔案名稱擴充的結果中包括以點(.)開頭的檔案名稱
extglob 開啟擴充的模式比對特徵(正常的運算式元字元來自Korn shell的檔案名稱擴充)
nocaseglob 如果設定,當執行檔案名稱擴充時,bash在不區分大小寫方式下匹配檔案名稱
nullglob 如果設定,bash允許沒有匹配任何檔案的檔案名稱模式擴充成一個空串,而不是它們本身
failglob 如果pattern沒有匹配到任意一個結果,則提示出錯。
含義說的很明白,這裡不舉例了