關於Linux Shell的展開與匹配
花括號展開
在非引號內的內容,如果用花括號包括,而且裡面用逗號分隔(至少包含一個逗號,可以是空內容),這樣花括號裡的內容會被展開成用空格分開的一個列表,花括號前後可以緊隨字首和字尾(前後綴都是可選的)。 例如: echo {a,b,c} echo hello,{world,pig} echo rep{,,,,,}eat 注意花括號展開,字首不能是$,因為${...}在shell中是變數波浪號展開
從波浪號~到第一個未被引號包含的斜槓/(如果沒有斜槓,則全部算上),作為波浪號字首。 在波浪號後面的字串作為一個可能的登入名:如果為空,被展開成該使用者的HOME變數,如果HOME變數未設定,則用使用者執行shell的主目錄替換。如果不為空,則按照該登入名的主目錄替換(原文:If this login name is the null string, the tilde is replaced with the value of theHOME
shell variable. If HOME
is
unset, the home directory of the user executing the shell is substituted instead. Otherwise, the tilde-prefix is replaced with the home directory associated with the specified login name.)
例如:
echo ~ # 顯示$HOME內容
HOME=/bin && echo ~ # 顯示/bin
unset HOME && echo ~ # 顯示當前使用者主目錄
echo ~root # 顯示root使用者主目錄
波浪號還可以與加減號和數字,產生一個遍歷資料夾堆疊的效果(關於資料夾堆疊,參考dirs、pushd、popd幾個命令)。
echo ~+ # 顯示$PWD
echo ~- # 顯示$OLDPWD
echo ~+2 # 顯示dirs中第3個內容,索引基於0
echo ~-3 # 顯示dirs中倒數第4個內容,索引基於0
如果無法展開,那就會原樣顯示,例如dir堆疊中只有1個內容,那麼~+1是無法展開的(這時只有~+0有效)。
Shell引數和變數展開
命令替換
將一些命令執行後,結果替換到該命令語句中,可以用$()和``括住的方法 命令替換是可以巢狀的。 例如: echo `date` echo $(date) echo $(echo `date` |awk '{print $4}')算術展開
程序替換
>(LIST)或<(LIST) LIST是一個命令,它執行時會從一個FIFO或/dev/fd/xxx這樣的地方讀取(對應>(LIST))或輸出(對應<(LIST)),而這個FIFO或/dev/fd/xxx作為外面命令的一個引數。 例如: echo -e 'haha hehe\nhaha2 hehe2' >a.txt # 生成了一個a.txt檔案,裡面有兩行 awk '{ print $2 }' <(cat a.txt) # 先為<(cat a.txt)生成了一個/dev/fd/63,關聯到cat a.txt,也就是說cat a.txt的輸出都被定向到/dev/fd/63這個檔案了,然後外圍的命令執行的是awk '{ print $2 }' /dev/fd/63,這樣列印的就是hehe和hehe2。字詞分隔
$IFS裡面的任何一個字元都可以作為分隔符,平時我們預設的就是回車、空格、tab符號。 (原文:The shell scans the results of parameter expansion, command substitution, and arithmetic expansion that did not occur within double quotes for word splitting.
The shell treats each character of $IFS
as a delimiter, and splits the results of the other expansions into words
on these characters. If IFS
is unset, or its value is exactly "'<space><tab><newline>'", the default, then any sequence
of IFS
characters serves to delimit words. If IFS
has
a value other than the default, then sequences of the whitespace characters "space" and "Tab" are ignored at the beginning and end of the word, as long as the whitespace character is in the value of IFS
(an IFS
whitespace
character). Any character in IFS
that is not IFS
whitespace,
along with any adjacent IF
whitespace characters, delimits a field. A sequence of IFS
whitespace
characters is also treated as a delimiter. If the value of IFS
is null, no word splitting occurs.
Explicit null arguments ("""" or "''") are retained. Unquoted implicit null arguments, resulting from the expansion of parameters that have no values, are removed. If a parameter with no value is expanded within double quotes, a null argument results and is retained.)
檔名展開
進行字詞分隔後,如果不指定-f選項,shell會搜尋"*","?","[",如果遇到了,就會認為是一個帶pattern的word,然後用字典序將符合的所有檔名替換過去,如果沒有檔名匹配:1 shell的nullglob選項關閉,則不進行檔名展開,保留word原樣;2 shell的nullglob開啟,則移除這個word。如果shell的nocaseglob選項開啟,則忽略大小寫。
當匹配檔名時(這裡指不包括資料夾),除非shell的dotglob被設定,否則.或./開頭的檔案都必須顯示指定,例如:
ls * # 列出當前資料夾中所有不以"."開頭的檔案
ls .* # 列出當前資料夾中所有以"."開頭的檔案
當匹配檔名時,"/"必需顯示匹配,例如:
ls ./* 和 ls ./*/*是不同的。
其它情況下,"."和普通字元一樣,例如:
*.txt和*txt都可以匹配a.txt
還有一個系統變數GLOBIGNORE,如果一個檔名匹配了一個pattern word,但是它也匹配了GLOBIGNORE,則它會被忽略,不過兩個特殊檔案一定會被忽略,就是"."和".."。
如果GLOBIGNORE開啟,那麼dotglob選項也會自動開啟,這樣會導致當你ls *時,其他以"."開頭的檔案也會被match,如果想忽略"."開頭的檔案,可以在GLOBIGNORE裡面新增一個".*"的匹配。如果GLOBIGNORE未設定,則dotglob關閉。
參考: