第 3 章目錄:
3.1 shell 語(yǔ)法
3.2 shell 命令
3.3 shell 函數(shù)
3.4 shell 參數(shù)
3.5 shell 展開(kāi)
3.6 重定向
3.7 命令執(zhí)行
3.8 shell 腳本
本文件內(nèi)容為 "3.5 shell 展開(kāi)"
3.5 小節(jié)目錄:
3.5.1 花括號(hào)展開(kāi) 對(duì)花括號(hào)中的表達(dá)式的展開(kāi)
3.5.2 波浪線展開(kāi)
3.5.3 shell 參數(shù)展開(kāi)
3.5.4 命令替換 把命令的輸出當(dāng)做參數(shù)使用
3.5.5 算術(shù)展開(kāi) 如何在 shell 表達(dá)式中進(jìn)行算術(shù)運(yùn)算
3.5.6 過(guò)程替換 一種對(duì)命令進(jìn)行讀寫(xiě)的方法
3.5.7 單詞分割 展開(kāi)結(jié)果是如何分割成獨(dú)立的參數(shù)的
3.5.8 文件名展開(kāi)
3.5.9 引用刪除
命令行被分割為 token 之后,就開(kāi)始進(jìn)行展開(kāi)畔派。一共有 7 種展開(kāi):
1沃但,花括號(hào)展開(kāi)
2抖所,波浪線展開(kāi)
3宴霸,參數(shù)和變量展開(kāi)
4译断,命令替換
5萧恕,算術(shù)展開(kāi)
6漾狼,單詞分割
7,文件名展開(kāi)
展開(kāi)的順序是:
1巡球,花括號(hào)展開(kāi)
2言沐,波浪線展開(kāi)
3,參數(shù)酣栈,變量,算術(shù)展開(kāi)和命令替換(在支持過(guò)程替換的系統(tǒng)上汹押,過(guò)程替換也在這里進(jìn)行)
4矿筝,單詞分割
5,文件名展開(kāi)
只有花括號(hào)展開(kāi)棚贾,單詞分割窖维,文件名展開(kāi)能改變展開(kāi)結(jié)果的單詞個(gè)數(shù)。
其他展開(kāi)一般把一個(gè)單詞展開(kāi)為另一個(gè)單詞妙痹,有兩個(gè)例外情況:'"$@"' 和 '"${NAME[@]}"'铸史。
所有展開(kāi)完成后,進(jìn)行引用刪除
3.5.1 花括號(hào)展開(kāi)
在花括號(hào)內(nèi)怯伊,可以是以逗號(hào)分隔的字符串琳轿,或者是一個(gè)序列表達(dá)式。在花括號(hào)前后耿芹,可以跟前綴和后綴崭篡。
花括號(hào)展開(kāi)支持嵌套,展開(kāi)的字符串是無(wú)序的吧秕,從左到右的順序被保留琉闪。
1,逗號(hào)分隔
# echo a{d,c,b}e
ade ace abe
前綴 a 和 后綴 e 與展開(kāi)結(jié)果的每一個(gè)字符串結(jié)合生成最終結(jié)果砸彬。
2颠毙,序列表達(dá)式
序列表達(dá)式的語(yǔ)法是:
'{X..Y[..INCR]}'
X,Y 是數(shù)字或單個(gè)字符砂碉,INCR 是步進(jìn)蛀蜜。
當(dāng) X,Y 是數(shù)字時(shí)绽淘,展開(kāi)為 X 到 Y 的所有數(shù)字涵防。數(shù)字可加前綴 0,如 01,001壮池,使展開(kāi)結(jié)果保持相同的寬度偏瓤。
當(dāng) X 或 Y 以 0 開(kāi)頭時(shí),shell 嘗試將生成結(jié)果保持相同寬度椰憋。必要時(shí)以 0 進(jìn)行填充厅克。
{01..100} 生成 001, 002, ..., 100
步進(jìn):
{1..10..2} 生成 1 3 5 7 9
當(dāng) X,Y 是字母時(shí)橙依,按字典序展開(kāi)证舟。X,Y 必須是相同類(lèi)型窗骑。當(dāng)給出步進(jìn)時(shí)女责,相鄰字母的距離為步進(jìn)的距離。默認(rèn)步進(jìn)為 1 或 -1(看具體情況)创译。
{a..g..2} 生成 a c e g
花括號(hào)展開(kāi)在其它展開(kāi)之前進(jìn)行抵知,任何對(duì)于其它展開(kāi)有特殊意義的字符都被保留。
在進(jìn)行花括號(hào)展開(kāi)時(shí)软族,bash 對(duì)于花括號(hào)的上下文和括號(hào)內(nèi)的文本內(nèi)容不做任何的語(yǔ)法解釋刷喜。
為避免與參數(shù)展開(kāi)產(chǎn)生沖突,字符串 '${' 不被認(rèn)為需要做花括號(hào)展開(kāi)立砸。
要進(jìn)行正確的花括號(hào)展開(kāi)掖疮,必須包含未被引用(unquoted)的 '{' 和 '}'。并且在括號(hào)中颗祝,至少有一個(gè)未被引用的 ',' 或者一個(gè)有效的“序列表達(dá)式”浊闪。
書(shū)寫(xiě)不正確的花括號(hào)展開(kāi)保留原樣。
把 '{' 和 ',' 引用起來(lái)吐葵,可避免被認(rèn)為是花括號(hào)展開(kāi)的一部分规揪。為避免與參數(shù)展開(kāi)產(chǎn)生沖突,字符串 '${' 不被認(rèn)為需要做花括號(hào)展開(kāi)温峭。
這個(gè)構(gòu)造典型的應(yīng)用場(chǎng)景是猛铅,當(dāng)字符串前綴太長(zhǎng)的時(shí)候,比如創(chuàng)建多個(gè)包含絕對(duì)路徑的文件時(shí)凤藏,使用花括號(hào)展開(kāi)可以簡(jiǎn)化命令行語(yǔ)句奸忽,如:
mkdir /usr/local/src/bash/{old,new,dist,bugs}
chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}} # 兩個(gè)子目錄
3.5.2 波浪線展開(kāi)
如果一個(gè)單詞以未被引用的 '~' 開(kāi)頭,這個(gè)單詞所有到斜線 '/'(如果有得話) 為止的字符被認(rèn)為是一個(gè) 波浪線前綴字符串(TILDE-PREFIX)揖庄。
如果在 “波浪線前綴字符串” 中沒(méi)有被引號(hào)引用的字符栗菜,那么所有波浪線之后的字符組成的字符串被當(dāng)做可能的 LOGIN NAME 對(duì)待。
如果 LOGIN NAME 是空字符串蹄梢,'~' 被替換為 'HOME' 變量的值疙筹。
如果 'HOME' 變量沒(méi)有設(shè)置,則替換為執(zhí)行 shell 的用戶(hù)的家目錄。
否則而咆,'~' 被替換為與 登錄名 關(guān)聯(lián)的家目錄霍比。
$ echo $HOME #HOME 非空
/Users/guli
$ echo ~ #打印當(dāng)前用戶(hù)家目錄
/Users/guli
$ echo ~guest #打印guest用戶(hù)家目錄
/Users/Guest
$ echo ~root #打印root用戶(hù)家目錄
/var/root
如果 波浪線前綴字符串 是 '~+',被替換為 'PWD' 變量的值暴备。
如果是 '~-'悠瞬,被替換為 'OLDPWD' 變量的值(如果存在的話)。
如果 波浪線前綴字符串 是一個(gè)數(shù)字涯捻,數(shù)字前跟著一個(gè) '+' 或 '-'浅妆,如 '~+N',則被替換為 目錄棧 的相應(yīng)順序的元素障癌。等同于 dirs +/-N 的效果凌外。
如果 '+' 或 '-' 沒(méi)有給出,默認(rèn)為 '+'涛浙。
如果 登錄名 是無(wú)效的趴乡,或者波浪線展開(kāi)失敗,則保留原樣蝗拿。
$ echo ~guset #登錄名 guset 是無(wú)效的
~guset
每個(gè)變量賦值會(huì)檢查緊跟在 ':' 或第一個(gè) '=' 后面是否有未被引號(hào)引用的 '~'。如果有蒿涎,會(huì)進(jìn)行波浪線展開(kāi)哀托。所以,我們可以通過(guò)這種方式賦值給 'PATH'劳秋,'MAILPATH'仓手,'CDPATH',shell 會(huì)用展開(kāi)后的結(jié)果賦值給變量玻淑。
下面是 bash 中的波浪線展開(kāi)的示例:
'~'
展開(kāi)為 '$HOME' 的值
'~/foo'
展開(kāi)為 '$HOME/foo'
'~fred/foo'
展開(kāi)為 用戶(hù)fred的及目錄的子目錄foo: /home/fred/foo
'~+/foo'
展開(kāi)為 '$PWD/foo'
'~-/foo'
展開(kāi)為 '{OLDPWD-'~-'}/foo'
'~N'
等同于執(zhí)行 'dirs +N' 的結(jié)果
'~+N'
等同于執(zhí)行 'dirs +N' 的結(jié)果
'~-N'
等同于執(zhí)行 'dirs -N' 的結(jié)果
3.5.3 Shell 參數(shù)展開(kāi)
'$' 符號(hào)引入了三種 shell 展開(kāi)嗽冒,包括 “參數(shù)展開(kāi)”,“命令替換” 和 “算術(shù)表達(dá)式”补履。
參數(shù)名或參數(shù)符號(hào)可以用花括號(hào)括起來(lái)添坊,使緊跟在參數(shù)名后面的字符與之分隔,這些字符與展開(kāi)的結(jié)果可共同構(gòu)成最后字符串箫锤。如 ${PATH}:/path/to/..
在參數(shù)展開(kāi)中使用花括號(hào)時(shí)贬蛙,'{' 是開(kāi)始符號(hào),右邊第一個(gè) '}' 是結(jié)束符號(hào)谚攒。
'}' 不能被轉(zhuǎn)義阳准,或被引號(hào)引用,也不能在一個(gè)嵌套的 “算術(shù)表達(dá)式”馏臭,或 “命令替換”野蝇,或者 “參數(shù)展開(kāi)”之中。
參數(shù)展開(kāi)的基本的形式是 ${PARAMETER},整體被替換為 PARAMETER 的值绕沈。如果 PARAMETER 是位置參數(shù)锐想,而且由兩個(gè)及以上的數(shù)字表示,這時(shí)必須使用花括號(hào):${10}七冲。另外當(dāng) PARAMETER 與其它字符相鄰連接時(shí)痛倚,也必須使用花括號(hào):${Var}lala。
如果 PARAMETER 的第一個(gè)字符是 "!"澜躺,會(huì)進(jìn)行“間接變量展開(kāi)”蝉稳。bash 使用 "!" 之后的部分作為變量名,變量進(jìn)行展開(kāi)掘鄙,變量展開(kāi)結(jié)果作為被引用的對(duì)象再進(jìn)行一次展開(kāi)耘戚。"!" 符號(hào)必須緊跟在左括號(hào) "{" 后面。但是 ${!PREFIX*} 和 ${!NAME[@]} 是例外操漠,在下面會(huì)介紹收津。
在下面將要介紹的例子中,WORD 可進(jìn)行 “波浪線展開(kāi)”浊伙,“參數(shù)展開(kāi)”撞秋,“命令替換” 以及 “算術(shù)展開(kāi)”。也就是說(shuō)嚣鄙,WORD 可以是 $VAR吻贿,$(CMD),$(EXPR)哑子,~ 形式的舅列。
如果 WORD 是字符串,就不會(huì)做展開(kāi)卧蜓,在這里不是作為變量名使用的帐要。
當(dāng)不進(jìn)行子字符串展開(kāi)時(shí),使用下面的形式弥奸,bash 會(huì)測(cè)試 PARAMETER
是否是 unset榨惠,或是否是空字符串(null)。
如果刪除冒號(hào) ':'其爵,只會(huì)測(cè)試 PARAMETER 是否是 unset(是否存在)冒冬。
'${PARAMETER:-WORD}'
如果 PARAMETER 是 unset 或者 null,最終展開(kāi)結(jié)果為 WORD 的展開(kāi)(普通字符串的展開(kāi)結(jié)果是原字符串保持不變摩渺,這里不是取 WORD 的值為最終結(jié)果)简烤。否則,使用 PARAMETER 的變量值為最終結(jié)果摇幻。
'${PARAMETER:=WORD}'
如果 PARAMETER 是 unset 或者 null横侦,將 WORD 的展開(kāi)結(jié)果賦值給PARAMETER(不是 WORD 的參數(shù)值)挥萌,最終結(jié)果為 PARAMETER 的值。但是“位置參數(shù)”和“特殊參數(shù)”不可通過(guò)這種方式賦值枉侧。
'${PARAMETER:?WORD}'
如果 PARAMETER 是 unset 或者 null引瀑,將 WORD 的展開(kāi)結(jié)果(如果未給出 WORD,會(huì)有一條消息)寫(xiě)入標(biāo)準(zhǔn)錯(cuò)誤輸出以及 shell榨馁,如果 shell 是非交互式的憨栽,就退出 shell。否則翼虫,使用 PARAMETER 的變量值最終結(jié)果屑柔。
'${PARAMETER:+WORD}'
如果 PARAMETER 是 unset 或者 null,結(jié)果是 nothing珍剑。否則 WORD 的展開(kāi)結(jié)果為最終結(jié)果掸宛。
'${PARAMETER:OFFSET}'
'${PARAMETER:OFFSET:LENGTH}'
1,當(dāng) PARAMETER 是普通變量時(shí)招拙,以字符為單位對(duì)參數(shù)值做截取唧瘾。
OFFSET: 從0開(kāi)始的位移,截取從位移處開(kāi)始别凤。
LENGTH: 截取的字符個(gè)數(shù)饰序。如果沒(méi)有寫(xiě)明 LENGTH,即截取從位移處到最后一個(gè)
字符规哪。
OFFSET 和 LENGTH 是“算數(shù)表達(dá)式”菌羽。這種展開(kāi)可被稱(chēng)為“子字符串展開(kāi)”。
LENGTH 必須大于等于1由缆,當(dāng)OFFSET是負(fù)數(shù)時(shí),表示從參數(shù)值的尾部向前截取猾蒂。
2均唉,當(dāng) PARAMETER 是位置參數(shù)時(shí),比如'@'肚菠,表示從OFFSET處開(kāi)始的LENGTH個(gè)位置參數(shù)舔箭。
3,當(dāng) PARAMETER 是以@或*為下標(biāo)的數(shù)組時(shí)蚊逢,表示從'${PARAMETER[OFFSET]}'開(kāi)始的 LENGTH 個(gè)數(shù)組變量层扶。
OFFSET 如果是負(fù)數(shù),它的計(jì)數(shù)從數(shù)組最大下標(biāo)+1的地方計(jì)算烙荷。
-1 是最后一個(gè)元素的索引
“子字符串展開(kāi)”用到數(shù)組上時(shí)會(huì)產(chǎn)生未知的結(jié)果镜会。
注意:負(fù)數(shù)的 offset 必須用空格與冒號(hào)':'隔開(kāi),以免和“:-展開(kāi)”混淆终抽。
對(duì)于字符串戳表,索引從 0 開(kāi)始桶至。(0-based)
對(duì)于位置參數(shù),索引從 1 開(kāi)始匾旭。(1-based)
對(duì)于數(shù)組镣屹,索引從 0 開(kāi)始。(0-based)
'${!PREFIX*}'
'${!PREFIX@}'
展開(kāi)結(jié)果為所有以 PREFIX 為前綴的變量的名字价涝。這些變量名以"IFS"變量的第
一個(gè)字符作為分隔符女蜈。
如果用的是@,而且在雙引號(hào)中展開(kāi)色瘩,每個(gè)變量名展開(kāi)為獨(dú)立的單詞伪窖。
如果用的是*,而且在雙引號(hào)中展開(kāi)泞遗,所有變量名展開(kāi)為一個(gè)單詞惰许。
# echo ${!BASH@}
BASH BASHOPTS BASHPID BASH_ALIASES BASH_ARGC BASH_ARGV BASH_CMDS BASH_COMMAND BASH_LINENO BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION
# for i in "${!BASH*}"; do echo "haha"; done
haha <=== 展開(kāi)為1個(gè)單詞,所以打印一次史辙。
# for i in "${!BASH@}"; do echo "haha"; done
haha <=== 展開(kāi)為獨(dú)立個(gè)單詞汹买,所以打印多次。
haha
haha
haha
haha
haha
haha
haha
haha
haha
haha
haha
haha
'${!NAME[@]}'
'${!NAME[*]}'
如果 NAME 是數(shù)組變量聊倔,展開(kāi)為數(shù)組索引(key)的列表晦毙。
如果 NAME 不是數(shù)組變量,當(dāng)變量存在時(shí)展開(kāi)為0耙蔑。
如果用的是@见妒,而且在雙引號(hào)中展開(kāi),每個(gè)key展開(kāi)為獨(dú)立的單詞甸陌。
'${#PARAMETER}'
展開(kāi)為參數(shù)值的長(zhǎng)度须揣。
如果參數(shù)是“*”或者“@”,展開(kāi)為位置參數(shù)的個(gè)數(shù)钱豁。
當(dāng)參數(shù)是以@或*為下標(biāo)的數(shù)組耻卡,展開(kāi)為數(shù)組中元素的個(gè)數(shù)。
'${PARAMETER#WORD}'
'${PARAMETER##WORD}'
將 WORD 的展開(kāi)結(jié)果作為匹配模式(如同文件名展開(kāi)中的通配符匹配)牲尺,去匹配參數(shù)值的開(kāi)始部分卵酪,匹配到的部分將被刪除。
使用“#”谤碳,表示最短匹配溃卡,
使用“##”,表示最長(zhǎng)匹配蜒简。
如果參數(shù)是“*”或者“@”瘸羡,對(duì)每個(gè)位置參數(shù)做上面的操作,
當(dāng)參數(shù)是以@或*為下標(biāo)的數(shù)組搓茬,對(duì)每個(gè)數(shù)組變量做如上的操作最铁。
'${PARAMETER%WORD}'
'${PARAMETER%%WORD}'
將 WORD 的展開(kāi)結(jié)果作為匹配模式(如同文件名展開(kāi)中的通配符匹配)讯赏,從參數(shù)值的尾部做匹配,匹配到的部分將被刪除冷尉。
使用“#”漱挎,表示最短匹配,
使用“##”雀哨,表示最長(zhǎng)匹配磕谅。
如果參數(shù)是“*”或者“@”,對(duì)每個(gè)位置參數(shù)做上面的操作雾棺,
當(dāng)參數(shù)是以@或*為下標(biāo)的數(shù)組膊夹,對(duì)每個(gè)數(shù)組變量做如上的操作。最終結(jié)果為所有被處理過(guò)的參數(shù)的列表捌浩。
'${PARAMETER/PATTERN/STRING}'
這個(gè)可視為上面兩個(gè)展開(kāi)的增強(qiáng)版放刨。PATTERN 的展開(kāi)結(jié)果作為匹配模式,對(duì)參數(shù)的值做最長(zhǎng)匹配尸饺,匹配的部分替換為 STRING进统。
一般只有第一個(gè)被匹配的部分才替換為 STRING,但如果 PATTERN 以 '/' 開(kāi)頭浪听,則所有匹配的部分都將被替換螟碎。
如果 PATTERN 以 '#' 開(kāi)頭,它必須從參數(shù)值的開(kāi)始部分進(jìn)行匹配迹栓。
如果 PATTERN 以 '%' 開(kāi)頭掉分,它必須從參數(shù)值的尾部進(jìn)行匹配。
如果 STRING=null克伊,匹配的部分將被刪除酥郭,而且 PATTERN 后面的 '/' 被忽略。
如果參數(shù)是“*”或者“@”愿吹,對(duì)每個(gè)位置參數(shù)做上面的操作褥民,
當(dāng)參數(shù)是以@或*為下標(biāo)的數(shù)組,對(duì)每個(gè)數(shù)組變量做如上的操作洗搂。最終結(jié)果為所有被處理過(guò)的參數(shù)的列表。
'${PARAMETER^PATTERN}'
'${PARAMETER^^PATTERN}'
'${PARAMETER,PATTERN}'
'${PARAMETER,,PATTERN}'
這個(gè)展開(kāi)用來(lái)修改參數(shù)值的字符的大小寫(xiě)载弄。
PATTERN 的展開(kāi)結(jié)果作為匹配模式
^ 將匹配的第一個(gè)字母的小寫(xiě)改為大寫(xiě)耘拇。
, 將匹配的第一個(gè)字母的大寫(xiě)改為小寫(xiě)。
^^ 將匹配的所有字母改為大寫(xiě)
,, 將匹配的所有字母改為小寫(xiě)
如果沒(méi)有給出 PATTERN宇攻,則默認(rèn)將 PATTERN 設(shè)為 ?惫叛,表示匹配任意一個(gè)字符。
如果參數(shù)是“*”或者“@”逞刷,對(duì)每個(gè)位置參數(shù)做上面的操作嘉涌,
當(dāng)參數(shù)是以@或*為下標(biāo)的數(shù)組妻熊,對(duì)每個(gè)數(shù)組變量做如上的操作。最終結(jié)果為所有被處理過(guò)的參數(shù)的列表仑最。
3.5.4 命令替換
命令替換允許使用命令的輸出替換命令本身扔役。
命令替換有兩種寫(xiě)法:
$(COMMAND) 或者 `COMMAND`
命令替換按如下方式進(jìn)行:
1,執(zhí)行命令警医,使用命令的標(biāo)準(zhǔn)輸出替換上述的命令替換表達(dá)式亿胸。
2,如果命令輸出的尾部有跟著換行符预皇,就將換行符刪除侈玄。
3,嵌入在命令輸出之中的換行符這時(shí)不會(huì)刪除吟温,但可能在進(jìn)行單詞分割的時(shí)候被刪除序仙。
'$(cat FILE)' 與 '$(< FILE)' 是相同的,但后者執(zhí)行速度更快鲁豪。
使用舊式的反引號(hào) '`' 時(shí)潘悼,反斜線 '' 失去特殊意義,僅當(dāng)反斜線后跟 '$'呈昔,'`'挥等,'' 時(shí),反斜線對(duì)其進(jìn)行轉(zhuǎn)義堤尾,否則只是普通字符肝劲。
使用 '$(COMMAND)' 時(shí),圓括號(hào)內(nèi)的所有字符不做特殊對(duì)待郭宝。
命令替換可進(jìn)行嵌套辞槐,使用 '`' 形式的命令替換時(shí),內(nèi)部的 '`' 要使用反斜線 '' 轉(zhuǎn)義粘室。
當(dāng)命令替換在雙引號(hào) "" 中進(jìn)行時(shí)榄檬,替換的結(jié)果不再進(jìn)行單詞分割和文件名展開(kāi)。
3.5.5 算術(shù)展開(kāi)
算術(shù)展開(kāi)允許對(duì)算術(shù)表達(dá)式進(jìn)行計(jì)算衔统,并使用計(jì)算結(jié)果替換算術(shù)展開(kāi)的整個(gè)表達(dá)式鹿榜。
其語(yǔ)法為:
$(( EXPRESSION ))
對(duì)于 EXPRESSION 的處理,如同使用了雙引號(hào) '"' 將之引用锦爵,大多數(shù)的特殊字符失去特殊意義舱殿,規(guī)則參考前面專(zhuān)門(mén)的章節(jié)。這里特殊的一點(diǎn)是险掀,EXPRESSION 中的 '"' 不做特殊對(duì)待沪袭。
EXPRESSION 中的所有 token 可能進(jìn)行:參數(shù)展開(kāi),命令替換樟氢,引用取消冈绊。
算術(shù)展開(kāi)可進(jìn)行嵌套侠鳄。
算術(shù)表達(dá)式的計(jì)算規(guī)則參見(jiàn)后面的小節(jié)。
如果 EXPRESSION 是無(wú)效的死宣,bash 打印一條消息到錯(cuò)誤輸出伟恶,替換不再進(jìn)行。
3.5.6 過(guò)程替換
如果系統(tǒng)支持命名管道(named pipes: FIFOs)十电,或者支持命名的打開(kāi)文件的 '/dev/fd' 方法知押,過(guò)程替換也被支持。
其形式如下:
<(LIST) 或者 >(LIST)
過(guò)程 LIST 執(zhí)行時(shí)鹃骂,其輸出或輸入與 FIFO 或者 '/dev/fd' 下的文件相連台盯。相連的文件名被當(dāng)做一個(gè)參數(shù)傳遞給當(dāng)前命令。
使用 '>(LIST)' 時(shí)畏线,對(duì)文件寫(xiě)入静盅,相同于給 LIST 提供輸入。
使用 '<(LIST)' 時(shí)寝殴,LIST的輸出寫(xiě)入文件蒿叠,讀取文件,可以獲得 LIST 的輸出蚣常。
注意 '<' 或 '>' 與圓括號(hào)之間沒(méi)有空格市咽,否則整個(gè)構(gòu)造被解釋為重定向。
過(guò)程替換可用時(shí)抵蚊,會(huì)與 參數(shù)和變量展開(kāi)施绎,命令替換,算術(shù)展開(kāi)同步進(jìn)行贞绳。
3.5.7 單詞分割
shell 對(duì) 參數(shù)展開(kāi)谷醉,命令替換,算術(shù)展開(kāi)的結(jié)果進(jìn)行掃描冈闭。對(duì)未被雙引號(hào)引用的部分進(jìn)行單詞分割俱尼。
shell 把 '$IFS' 中的每一個(gè)字符當(dāng)做分隔符,對(duì)其他展開(kāi)生成的結(jié)果進(jìn)行單詞分割萎攒。
如果 'IFS' 沒(méi)有設(shè)置遇八,或者其值正好是默認(rèn)值 '<space><tab><newline>',之前進(jìn)行的展開(kāi)生成的結(jié)果的開(kāi)始部分和結(jié)束部分耍休,如果是由這三個(gè)字符組成的連續(xù)字符串刃永,將不做處理。在中間的話羹应,會(huì)發(fā)揮單詞分隔符的作用。
如果 'IFS' 的值不是默認(rèn)值次屠,只要空白字符在 'IFS' 之中(這時(shí)的空白符可稱(chēng)為 IFS 空白符)园匹,那么由空白字符(space 和 tab)組成的連續(xù)字符串雳刺,出現(xiàn)在展開(kāi)結(jié)果的開(kāi)始部分和結(jié)束部分時(shí),被忽略不做處理裸违。
任何在 'IFS' 中的非空白符掖桦,與毗連的 'IFS' 空白符一起作為分隔符使用。單詞中的 'IFS' 空白符字符串也作為分隔符使用供汛。如果 'IFS' 是空字符串枪汪,不進(jìn)行單詞分割。
顯式出現(xiàn)的空字符串("" 或者 '')將被保留怔昨。由參數(shù)值為空的參數(shù)展開(kāi)生成的未被引號(hào)引用的隱式空字符串雀久,將被刪除。如果參數(shù)值為空的參數(shù)展開(kāi)在雙引號(hào) "" 中進(jìn)行趁舀,空字符串被保留赖捌。
如果之前沒(méi)有進(jìn)行任何展開(kāi),單詞分割也不會(huì)進(jìn)行矮烹。
3.5.8 文件名展開(kāi)
目錄:
3.8.1 模式匹配 shell 如何進(jìn)行模式匹配
完成單詞分割之后越庇,除非設(shè)置了 '-f' 選項(xiàng)(set 命令),bash 依次掃描每個(gè)單詞奉狈,尋找 '*', '?' 和 '['卤唉,如果出現(xiàn)其中一個(gè),該單詞被認(rèn)為是一個(gè) PATTERN仁期,并替換為一組按字典序排序的匹配的文件名桑驱。
如果沒(méi)找到匹配的文件名,而且 shell 選項(xiàng) 'nullglob' 是關(guān)閉的蟀拷,該單詞保留原樣碰纬。
如果沒(méi)找到匹配的文件名问芬,而且 shell 選項(xiàng) 'nullglob' 是開(kāi)啟的,該單詞被刪除此衅。
如果沒(méi)找到匹配的文件名,而且 shell 選項(xiàng) 'failglob' 是開(kāi)啟的挡鞍,打印一條錯(cuò)誤信息骑歹,不執(zhí)行命令墨微。
如果 shell 選項(xiàng) 'nocaseglob' 開(kāi)啟,匹配時(shí)忽略大小寫(xiě)。
當(dāng)一個(gè) pattern 用作文件名展開(kāi)時(shí)最域,字符 '.' 位于文件名首部的 或者'.' 跟在 '/' 之后('/.')時(shí)谴分,必須進(jìn)行顯式地匹配,除非開(kāi)啟了 'dotglob' 選項(xiàng)牺蹄。
匹配文件名時(shí)薄翅,字符 '/' 必須進(jìn)行顯式地匹配。除此之外翘魄,字符 '.' 不被特殊對(duì)待。
參見(jiàn) 'shopt' 命令詳細(xì)了解 'nocaseglob'训措,'nullglob'光羞,'failglob' 以及 'dotglob' 選項(xiàng)。
shell 變量 'GLOBIGNORE' 可用于限制文件名的匹配纱兑。
如果設(shè)置了這個(gè)變量潜慎,每個(gè)匹配的文件名如果同時(shí)匹配 'GLOBIGNORE' 中的 pattern,這個(gè)文件名從匹配結(jié)果列表中刪除铐炫。
'GLOBIGNORE' 變量被設(shè)置且非空時(shí),文件名 '.' 和 '..' 總是被忽略科贬。
'GLOBIGNORE' 變量設(shè)置為非空值時(shí)鳖悠,'dotglob' 選項(xiàng)被開(kāi)啟,所以所有其他以 '.' 開(kāi)始的文件名也會(huì)被匹配憎账。
如果想要忽略以 '.' 開(kāi)始的文件名卡辰,可將 '.*' 設(shè)置為 'GLOBIGNORE' 變量的其中一個(gè) pattern邪意。'GLOBIGNORE' 變量未設(shè)置時(shí)反砌,'dotglob' 選項(xiàng)被關(guān)閉。
3.5.8.1 模式匹配
pattern 中的字符,除了下面描述的特殊 pattern 字符嚷兔,將匹配其自身。NUL 字符不可出現(xiàn)在 pattern 中同衣。
'' 字符將下面的特殊字符轉(zhuǎn)義為普通字符壶运,以匹配其自身,匹配時(shí)埠况,'' 字符自身被忽略。
希望特殊字符匹配其自身時(shí)棵癣,必須將其引用(quoted)。
'*'
匹配任意字符串狈谊,包括 空字符串河劝。
shell 選項(xiàng) 'globstar' 開(kāi)啟時(shí),'**' pattern 匹配所有文件和 0+ 個(gè)目錄及子目錄赎瞎。
'**/' 只匹配目錄和子目錄煎娇。
'?'
匹配任意單個(gè)字符
'[...]'
匹配括號(hào)中任意一個(gè)字符。
一對(duì)以 '-' 分隔的字符表示 RANGE EXPRESSION(范圍表達(dá)式)缓呛。匹配這對(duì)字符之間(包括這對(duì)字符)的任意一個(gè)字符哟绊。
如果左括號(hào) '[' 后面第一個(gè)字符是 '!' 或者 '^',匹配括號(hào)內(nèi)所有字符之外的
任意一個(gè)字符。
'-' 字符放在第一個(gè)位置铣耘,或最后一個(gè)位置時(shí)以故,可以被匹配。
']' 字符放在第一個(gè)位置炉媒,可以被匹配昆烁。
范圍表達(dá)式的排序順序由當(dāng)前 locale 語(yǔ)系 和 'LC_COLLATE' (如果已設(shè)置)的值決定。
比如白粉,根據(jù)默認(rèn)的 C locale鼠渺,'[a-dx-z]' 等效于 '[abcdxyz]'。許多其他 locale 按照字典序排序奕扣,這時(shí) '[a-dx-z]' 可能等效于 '[aBbCcDdxXyYz]'掌敬。
可通過(guò)設(shè)置 'LC_COLLATE' 或 'LC_ALL' 為 'C',強(qiáng)制使用傳統(tǒng)的 'C' 語(yǔ)系排序楷兽。
在中括號(hào)中华临,CHARACTER CLASSES(特定字符集)可由 '[:'CLASS':]' 指定。
POSIX 標(biāo)準(zhǔn)定義的 CLASS 包括:
alnum alpha ascii blank cntrl digit graph
lower print punct space upper word xdigit
特定字符集可匹配屬于該字符集的任意一個(gè)字符揭厚。'word' 匹配 字母扶供,數(shù)字 和 下劃線 '_'椿浓。
Within [ and ], an EQUIVALENCE CLASS can be specified usingthe syntax [=C=], which matches all characters with the same collation weight (as defined by the current locale) as the character C.
Within [ and ], the syntax [.SYMBOL.] matches the collating symbol SYMBOL.
如果 shell 選項(xiàng) 'extglob' 開(kāi)啟(使用 'shopt' 命令)闽晦,可使用下列的擴(kuò)展 pattern提岔。在下面的描述中, PATTERN-LIST 是由 '|' 分隔的一個(gè)
或多個(gè) pattern 組成的列表荠瘪。
復(fù)合 pattern 可由下面的一個(gè)或多個(gè) pattern 組成赛惩。
'?(PATTERN-LIST)'
匹配 0 個(gè)或 1個(gè) 給出的 patterns。
'*(PATTERN-LIST)'
匹配 0 個(gè)或 多個(gè) 給出的 patterns。
'+(PATTERN-LIST)'
匹配 1 個(gè)或 多個(gè) 給出的 patterns褒搔。
'@(PATTERN-LIST)'
匹配給出的 patterns 的其中一個(gè)喷面。
'!(PATTERN-LIST)'
匹配給出的 patterns 之外的任意字符串。
3.5.9 引用取消
前面的展開(kāi)完成之后琳状,所有未被引用的 \盒齿,' 和 ",除了由之前的展開(kāi)生成的翎承,都被刪除符匾。