- 論壇徽章:
- 0
|
+-------------+ 單引號
|------------------------->| |--------------------------|
| ----------------------->| 1.分隔成記號|---- ---------------| |
| | ------------------->| | 雙引號 | |
| | | +-------------+ | |
| | | || | |
| | |讀取下一個命令 \/ | |
| | | +-------------------------------------------+ | |
| | | | 2. | | |
| | ------| 檢驗(yàn)第一個記號 | | |
| | |開放的關(guān)鍵字 其他關(guān)鍵字 | | |
| | | 非關(guān)鍵字 | | |
| | +-------------------------------------------+ | |
| | || | |
| | \/ | |
| | +-----------------------------+ | |
| | 擴(kuò)展別名 | 3. 檢驗(yàn)第一個記號 | | |
| |------------| 別名 | | |
| | 不是別名 | | |
| +-----------------------------+ | |
| || | |
| \/ | |
| +--------------+ | |
| | 4.大括號擴(kuò)展 | | |
| +--------------+ | |
| || | |
| \/ | |
| +--------------+ | |
| | 5.~符號擴(kuò)展 | | |
| +--------------+ | |
| || | |
| \/ | |
| +--------------+ 雙引號 | |
| | 6.參數(shù)擴(kuò)展 |
Shell從標(biāo)準(zhǔn)輸入或腳本中讀取的每行稱為一個管道行,它包含一個或多個由0個或多個管道字符(|)分隔的命令。對每一個管道行,進(jìn)行12個步驟的處理。
結(jié)合上面的插圖,這里給出命令行的12個步驟。
1. [color="blue"]將命令行分成由固定元字符集分隔的記號:
[color="red"]SPACE, TAB, NEWLINE, ; , (, ), , |, &
記號類型包括單詞,關(guān)鍵字,I/O重定向符和分號。
2.[color="blue"]檢測每個命令的第一個記號,查看是否為不帶引號或反斜線的關(guān)鍵字。如果是一個開放
的關(guān)鍵字,如if和其他控制結(jié)構(gòu)起始字符串,function,{或(,則命令實(shí)際上為一復(fù)合命令。shell在內(nèi)部對復(fù)合命令進(jìn)行處理,讀取下一個命
令,并重復(fù)這一過程。如果關(guān)鍵字不是復(fù)合命令起始字符串(如then等一個控制結(jié)構(gòu)中間出現(xiàn)的關(guān)鍵字),則給出語法錯誤信號。
3.[color="blue"]依據(jù)別名列表檢查每個命令的第一個關(guān)鍵字。如果找到相應(yīng)匹配,則替換其別名定義,并退回第一步;否則進(jìn)入第4步。該策略允許遞歸別名,還允許定義關(guān)鍵字別名。如alias procedure=function
4.[color="blue"]執(zhí)行大括號擴(kuò)展,例如a{b,c}變成ab ac
5.[color="blue"]如果~位于單詞開頭,用$HOME替換~。使用usr的主目錄替換~user。
6.[color="blue"]對任何以符號$開頭的表達(dá)式執(zhí)行參數(shù)(變量)替換
7.[color="blue"]對形式$(string)的表達(dá)式進(jìn)行命令替換
[color="red"]這里是嵌套的命令行處理。
8.[color="blue"]計算形式為$((string))的算術(shù)表達(dá)式
9.[color="blue"]把行的參數(shù),命令和算術(shù)替換部分再次分成單詞,這次它使用$IFS中的字符做分割符而不是步驟1的元字符集。
10.[color="blue"]對出現(xiàn)*, ?, [ / ]對執(zhí)行路徑名擴(kuò)展,也稱為通配符擴(kuò)展
11. [color="blue"]按命令優(yōu)先級表(跳過別名),進(jìn)行命令查尋
12.[color="blue"]設(shè)置完I/O重定向和其他操作后執(zhí)行該命令。
關(guān)于引用
1. 單引號跳過了前10個步驟,不能在單引號里放單引號
2. 雙引號跳過了步驟1~5,步驟9~10,也就是說,只處理6~8個步驟。
也就是說,雙引號忽略了管道字符,別名,~替換,通配符擴(kuò)展,和通過分隔符分裂成單詞。
雙引號里的單引號沒有作用,但雙引號允許參數(shù)替換,命令替換和算術(shù)表達(dá)式求值?梢栽陔p引號里包含雙引號,方式是加上轉(zhuǎn)義符"\",還必須轉(zhuǎn)義$, `, \。
[color="blue"]摘自man bash 的一段話來解釋雙引號:
Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, `, \, and, when history expansion is enabled, !. The characters $ and ` retain their special
meaning within double quotes. The backslash retains its special meaning only when followed by one of the following characters: $, `, ", \, or . A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an ! appearing in double quotes is escaped using a backslash. The backslash preceding the ! is not removed.
下面man bash的一段話來解釋命令替換$()和``
When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or \. The first backquote not preceded by a backslash terminates the command substitution. When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.
[color="blue"]
要思考的問題:
1.echo `echo \\\z` 的輸出 和 echo `echo \\\\z` 的輸出。
2.在bash中:
$echo "\\"
輸出:\
$A='\\'
$echo "$A"
輸出:\\
解釋原因。
原因:這與bash命令行處理的順序有關(guān)。bash中對引用(單雙引號和\)的處理在對參數(shù)擴(kuò)展(展開變量)之前,所以將$A的值代入命令行之后bash就不再解釋轉(zhuǎn)義或稱作逃逸字符。有時為了讓shell再次進(jìn)行命令行的一系列處理,需要使用eval。
其實(shí)有兩種方法讓輸出結(jié)果為\:
方法一、echo -e "$A"
方法二、eval echo "$A"
其中方法一是通過改變echo命令的執(zhí)行方式達(dá)到結(jié)果,
方法二是通過改變shell處理來達(dá)到結(jié)果。
3.echo `echo \\` 與 echo $(echo \\)的輸出分別是什么?解釋原因。
原因: ``里面的\是一個特殊字符,可以用它來引用特殊的字符(當(dāng)然包括它自身\),而$()里面的\只是普通字符。
echo `echo \\`命令,里層的echo \\得到的結(jié)果\,于是外層命令為echo \,輸出結(jié)果就為空了。
echo $(echo \\)命令,里層的\不再作為特殊字符,其輸出就是\\,于是外層命令為echo \\,輸出結(jié)果就為\了。
[color="blue"]
本文來自ChinaUnix博客,如果查看原文請點(diǎn):http://blog.chinaunix.net/u2/63316/showart_2152062.html |
|