Unix 的神秘之處就在於它的那些稀奇古怪的命令。比如在兩個
斜杠之間是否需要加一個點,或者連字元后是否需要加引號。
要真正理解這些命令的話,就必須知道這些命令行是怎樣被解釋的。
Shell 程序(sh, ksh, csh, 或者其他變種) 讀入並分析命令行,所以,命令行其實是對shell 程序的輸入參數而已。
我們先來看一下讀入的順序:
1. 命令歷史替換 (除了Bourne shell)
2. 分開單詞,包括特殊字元
3. 更新命令歷史(除了Bourne shell)
4. 解釋單引號和雙引號
5. 別名替換(除了Bourne shell)
6. 輸入輸出重定向 (< > 和 |)
7. 變數替換 (以 $開頭的變數)
8. 命令替換 (命令s inside back quotes)
9. 文件名擴展 (file name wild cards)
你可以看到 Bourne shell 沒有命令歷史和別名替換的步驟,因為
Bourne shell 不包括這些功能。
1、命令歷史替換
如果你在Korn shell (ksh), C shell (csh), 或者其他類似的 shell 設置了命令歷史。
命令行就會在執行之前存入一個歷史文件,你以後可以用
$ history
查看這些命令。
命令前面有一個數字:
13 ls *.txt
14 cd $HOME
15 ls *.log
在 Korn shell 裡面,你可以用 r 加上數字來取回以前用過的命令。例如用r 13 就可以重複以上的 ls.$.txt 命令。
在C shell 裡面,使用感嘆號並且沒有空格來替換r : !13。
處理命令行時,shell 首先檢查命令替換,在歷史文件裡面尋找,取回每個命令,然後寫入新的命令行。當然有關歷史的處理不止簡單的這些步驟。我們會在以後的文章中單獨討論。
2、分開單詞
接下來的步驟就是把單詞和特殊字元分開了。一個單詞被shell 程序認為是命令的一部分。以下的命令用長格式列出當前目錄並尋找包含mjb 的行。
ls -l|grep mjb
這個命令的單詞包括:ls, -l, |, grep 以及mjb。單詞也可以包含在引號裡面。
在以下的命令中,一個長格式列表搜索創建於"Sep 07." 的文件。
ls -l|grep "Sep 07"
在這裡,"Sep 07 " 作為一個單詞被放入引號。
3、更新歷史清單
一旦單詞被確定,這個命令就寫道歷史文件的結尾。
4、 解釋單引號和雙引號
單引號裡面的變數,不被處理,雙引號裡面的會被展開。
可以輸入以下的命令來檢驗:
echo $PATH
echo $PATH
echo "$PATH"
第一行顯示 $PATH 變數的值,第二行顯示單詞 $PATH,第三行顯示 $PATH 變數的值。
5、別名替換
每個命令的第一個單詞會和別名列表比較。下面的例子中,ls 和 grep 在別名清單中被檢查,作別名替換。別名就是用一個命令來
替換另外一個命令的方法。例如:以下的命令:
alias ll ls -l
建立一個新的命令 ll,當你輸入
ll *.txt
時,就像輸入 ls -l *.txt 。
6、管道和重定向
到了這裡,shell 程序「看」完了命令行里的所有單詞。
對於 |, >, <, >>, 和其他的重定向命令,找到一個,就建立管道或者重定向。
7、變數擴展
現在命令行內的變數擴展,所有包含在雙引號內的變數被替換成對應的值。
8、命令替換
命令替換查找反引號,執行括在其中的命令以及參數,然後使用運行結果作為參數傳遞給要執行的命令,例如:
ls -l `ls -p|grep /`|more
命令 ls -p 產生帶給目錄加註反斜杠的目錄列表,如:
ls -p
STARTUP
file.txt
file2.txt
mystuff/
xdir/
加在後面的 grep / 命令只選擇那些包含反斜杠的項:
ls -p|grep /
mystuff/
xdir/
把整個命令用反引號引進后,生成的結果作為參數傳遞給 ls -l
ls -l `ls -p|grep /`|more
這等同於:
ls -l mystuff/ xdir/|more
9、通配符
命令處理其尋找文件名的通配符並擴展他們。通配符包括:
* 和 ? 以及中括弧,例如:
ls -l [abc]*
顯示那些以 a 或 b 或 c 結尾的文件或者目錄。
執行
最後命令被執行,這就完成了整個的流程。
需要指出的是:在上述第八步中,當處理反引號中的命令時,
先把它分離出來,作為一個單獨的命令按照以上1-9步來處理,
對於用分號隔開的命令也一樣。
[火星人
]
想知道「shell 程序怎樣解釋命令」的進來已經有545次圍觀
http://coctec.com/docs/linux/show-post-137422.html