3.shell 基本特性之~ shell展開(kāi)詳解

第 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)生成的翎承,都被刪除符匾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末啊胶,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子趣倾,更是在濱河造成了極大的恐慌某饰,老刑警劉巖部凑,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涂邀,死亡現(xiàn)場(chǎng)離奇詭異箱锐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)浩聋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)臊恋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人坊夫,你說(shuō)我怎么就攤上這事撤卢。” “怎么了智听?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵到推,是天一觀的道長(zhǎng)惕澎。 經(jīng)常有香客問(wèn)我,道長(zhǎng)悔雹,這世上最難降的妖魔是什么欣喧? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任唆阿,我火速辦了婚禮,結(jié)果婚禮上驯鳖,老公的妹妹穿的比我還像新娘。我一直安慰自己扭弧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布呼巴。 她就那樣靜靜地躺著衣赶,像睡著了一般厚满。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上遵馆,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天敲街,我揣著相機(jī)與錄音严望,去河邊找鬼像吻。 笑死,一個(gè)胖子當(dāng)著我的面吹牛拨匆,可吹牛的內(nèi)容都是我干的惭每。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼宏赘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼黎侈!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起贴汪,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤扳埂,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后聂喇,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體希太,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年矾湃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了堕澄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛙紫。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖僵驰,靈堂內(nèi)的尸體忽然破棺而出唁毒,到底是詐尸還是另有隱情,我是刑警寧澤粉私,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布近零,位于F島的核電站,受9級(jí)特大地震影響猪瞬,放射性物質(zhì)發(fā)生泄漏入篮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一痊项、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鞍泉,春花似錦、人聲如沸边器。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至涩拙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間工育,已是汗流浹背搓彻。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工好唯, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留燥翅,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓靶端,卻偏偏與公主長(zhǎng)得像凛膏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子台谍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理趁蕊,服務(wù)發(fā)現(xiàn),斷路器是己,智...
    卡卡羅2017閱讀 134,628評(píng)論 18 139
  • shell中各種括號(hào)的使用方法(摘自網(wǎng)絡(luò)) 在這里我想說(shuō)的是幾種shell里的小括號(hào),大括號(hào)結(jié)構(gòu)和有括號(hào)的變量任柜,命...
    草中人閱讀 522評(píng)論 0 0
  • Bash內(nèi)置基本變量 PWD : 顯示當(dāng)前的工作目錄 OLDPWD : 顯示上一次的工作目錄 ~:用戶(hù)家目錄 - ...
    魏鎮(zhèn)坪閱讀 1,516評(píng)論 0 6
  • bash的工作特性之命令執(zhí)行狀態(tài)返回值 一摔认、shell是什么绸栅? Shell本身是一個(gè)用C語(yǔ)言編寫(xiě)的程序,它是用戶(hù)使...
    隨風(fēng)而落隨心而動(dòng)閱讀 1,309評(píng)論 0 1
  • 思想決定了你的高度蓖柔,執(zhí)行決定了你能走多遠(yuǎn)风纠。 從思想上說(shuō)服一個(gè)人接受你,很難镐捧,改變一個(gè)人更難臭增。 我覺(jué)得我希望通過(guò)就事...
    早晚刷牙閱讀 153評(píng)論 0 1