周海漢 /文
2010.6.10
bash shell的擴充,指shell在分析輸入命令時的一種將命令展開的操作。 有7種擴充方式。參考一下man bash的擴充頁:
擴充(EXPANSION)<br /> 命令列的擴充是在拆分成詞之後進行的。有七種類型的擴充: brace expansion(花括弧擴充), tilde expan‐<br /> sion(波浪線擴充), parameter and variable expansion(參數和變數擴充), command substi‐<br /> tution(命令替換), arithmetic expansion(算術擴充), word splitting(詞的拆分), 和 path‐<br /> name expansion(路徑擴充).<br /> 擴充的順序是:brace expansion, tilde expansion, parameter, variable 和 arith‐<br /> metic expansion 還有 command substitution (按照從左至右的順序), word splitting,<br /> 最後是 pathname expansion.<br /> 還有一種附加的擴充:process subtitution (進程替換) 只有在支援它 的系統中有效。<br /> 只有 brace expansion, word splitting, 和 pathname expansion<br /> 在擴充前後的詞數會發生改變;其他擴充總是將一個詞擴充為一個詞。 唯一的例外是上面提到的 "$@" 和 "${name[@]}" (參見<br /> PARAMETERS參數)。<br /> Brace Expansion<br /> Brace expansion 是一種可能產生任一字元串的機制。這種機制類似於 pathname expansion,<br /> 但是並不需要存在相應的檔案。 花括弧擴充的模式是一個可選的 preamble(前置字元),<br /> 後面跟著一系列逗號分隔的字串,包含在一對花括弧中, 再後面是一個可選的 postscript(附言)。<br /> 前置被添加到花括弧中的每個字串前面,附言被附加到每個結果字串之後, 從左至右進行擴充。<br /> 花括弧擴充可以嵌套。擴充字元串的結果沒有排序;而是保留了從左至右的順序。 例如, a{d,c,b}e 擴充為 `ade ace abe'。<br /> 花括弧擴充是在任何其他擴充之前進行的,任何對其他擴充有特殊意義的字元 都保留在結果中。它是嚴格字面上的。 Bash<br /> 不會對擴充的上下文或花括弧中的文本做任何語義上的解釋。<br /> 正確的花括弧擴充必須包含沒有引用的左括弧和右括弧,以及至少一個沒有 引用的逗號。任何不正確的運算式都不會被改變。可以用反斜線來引用 { 或 ,<br /> 來阻止將它們識別為花括號運算式的一部分。 為了避免與參數擴充衝突,字串 ${ 不被認為有效組合。<br /> 這種結構通常用來簡寫字串的公用首碼遠比上例中為長的情況,例如:<br /> mkdir /usr/local/src/bash/{old,new,dist,bugs}<br /> 或者:<br /> chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}<br /> 花括弧擴充導致了與曆史版本的 sh 的一點不相容。在左括弧或右括弧作為詞的一部分出現時, sh 不會對它們進行特殊處理,會在輸出中保留它們。<br /> Bash 將括弧從花括弧擴充結果的詞中刪除。例如,向 sh 輸入 file{1,2} 會導致不變的輸出。同樣的輸入在 bash<br /> 進行擴充之後,會輸出 file1 file2 . 如果需要同 sh 嚴格地保持相容,需要在啟動 bash 的時候使用 +B 選項,或者使用<br /> set 命令加上 +B 選項來禁用花括弧擴充 (參見下面的 shell 內建命令(SHELL BUILTIN COMMANDS) 章節)。<br />
大括弧(花括弧)擴充方式也有意思。
樣本1:操作多個檔案名稱有共同點的檔案
zhouhh@zhh64:~/brace$ ls
bk
zhouhh@zhh64:~/brace$ touch file{source,target,info,readme}.txt
zhouhh@zhh64:~/brace$ ls
bk fileinfo.txt filereadme.txt filesource.txt filetarget.txt
zhouhh@zhh64:~/brace$ echo file{1,2,3,4}.txt
file1.txt file2.txt file3.txt file4.txt
zhouhh@zhh64:~/brace$ touch file{1,2,3,4}.txt
zhouhh@zhh64:~/brace$ ls
bk file1.txt file2.txt file3.txt file4.txt
樣本2:一個命令將幾個檔案名稱有規律的檔案轉移到一個目錄
zhouhh@zhh64:~/brace$ ls bk
zhouhh@zhh64:~/brace$ mv file{1,2,3,4}.txt bk/.
zhouhh@zhh64:~/brace$ ls bk
file1.txt file2.txt file3.txt file4.txt
zhouhh@zhh64:~/brace$
樣本3:備份
zhouhh@zhh64:~/brace$ touch mydata.log
zhouhh@zhh64:~/brace$ vi back.sh
zhouhh@zhh64:~/brace$ chmod +x back.sh
zhouhh@zhh64:~/brace$ cat back.sh
set -x #偵錯模式
bkdate=`date +%F` #日期
cp mydata{,$bkdate}.log #將log備份為帶日期格式
zhouhh@zhh64:~/brace$ ls
back.sh bk mydata.log
zhouhh@zhh64:~/brace$ ./back.sh
+++ date +%F
++ bkdate=2010-06-10
++ cp mydata.log mydata2010-06-10.log
zhouhh@zhh64:~/brace$ ls
back.sh bk mydata2010-06-10.log mydata.log
樣本4 處理多個有規律檔案名稱
zhouhh@zhh64:~/brace$ echo /var/log/messages.{1..3}
/var/log/messages.1 /var/log/messages.2 /var/log/messages.3
zhouhh@zhh64:~/brace$ echo file{a..d}{1..3}.txt
filea1.txt filea2.txt filea3.txt fileb1.txt fileb2.txt fileb3.txt filec1.txt filec2.txt filec3.txt filed1.txt filed2.txt filed3.txt
樣本5 for迴圈
zhouhh@zhh64:~/brace$ for i in {1..9..3}
> do
> echo $i
> done
1
4
7
參考:
http://www.thegeekstuff.com/2010/06/bash-shell-brace-expansion/#more-4614