shell的強大,很大程度上得益於對命令列做了額外的處理,你可以再命令中嵌入其他命令,在引數中嵌入其他命令,或者嵌入變數,插入路徑萬用字元,插入表示式,shell都能幫你處理的很好,就因為shell能做這些,所以shell才如此強大。
廢話少說,直接開始。
首先還是要囉嗦兩句,說說shell處理命令的過程,網上有篇文章寫的很不錯,很詳細,不過我忘記在那兒了,有興趣的同學可以找找看,用google!我只想說一句:弄清楚shell處理命令的過程很重要。
簡單的說下shell處理命令的過程是:
1.先按( ) < > ; l &把命令分割成乙個個的token
2.檢查第乙個token是不是乙個開放的關鍵字,如for if 擴充套件
5.執行波浪號~擴充套件
6.執行變數擴充套件
7.執行命令替換
8.執行算術表示式計算
9.把生成的新命令按ifs分割成token
10.執行路徑擴充套件
11.按優先順序查詢命令,先從內建,再從path。
12.設定好重定向等,執行命令
過程大致是這樣,這裡寫的很錯略,只是為了幫助更好的了解後文。這裡要說的就是4,5,6,7,8,10
在shell中,有六種擴充套件:花括號、波浪號、變數擴充套件、命令替換、算術擴充套件和路徑擴充套件。
花括號擴充套件:
簡單點說就是給一組字串加上相同的字首和字尾,生成一組新的字串。字首和字尾都可以為空。
[jjz@localhost ~]$ echo ad可以使用乙個範圍,只支援數字和字母。abd acd
[jjz@localhost ~]$ echo a
ab ac
[jjz@localhost ~]$ echo a花括號還可以巢狀,逐層有序的進行處理。a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
[jjz@localhost ~]$ echo a
aa ab ac ad ae af
[jjz@localhost ~]$ echo a,}可以認為先生成a,然後生成a1 a2 ab aca1 a2 ab ac
要注意的地方:
花括號裡只有字面量,不要試圖使用變數,花括號不支援,比如
[jjz@localhost ~]$ a=1並沒有生成1 2 3 4 5 6 7 8 9 10。對大括號擴充套件來說,生成的結果是 ,那為什麼我們看到的會是呢?這就和shell的命令處理順序有關了,我們再看看shell的命令處理順序,花括號擴充套件是在第四步,到了第六步,會執行變數擴充套件,這時候相當於 命令[jjz@localhost ~]$ echo
echo$a被替換成了1,當然輸出的就是了。
花括號裡至少要有乙個逗號,也就是至少要有兩項
兩項之間不能有空格,也就是逗號前後不能有空格,否則不進行花括號擴充套件。
波浪號擴充套件
波浪號擴充套件就是對~進行處理。一般情況下,我們認為~代表了自己的主目錄,其實事情並非這麼簡單。進行波浪號替換的條件是很苛刻的。
首先,進行波浪號擴充套件的前提是波浪號必須位於乙個token的開頭,簡單的說,~前面應該是空格。
然後,shell會分析波浪號之後,第乙個/或:之前的未被引號括起來的字串(如果沒有/,那就取波浪號之後的所有字元),這個字串叫做"波浪號字首(tilde-prefix)"(注意,所謂波浪號字首其實是出現在波浪號後面的),波浪號字首的取值和對應的處理方式是:
如果波浪號字首是個有效使用者名稱,則波浪號和波浪號字首一起替換成這個使用者的主目錄
如果波浪號字首為空,則嘗試把波浪號替換成home,如果home沒有被設定,則將波浪號替換成當前使用者主目錄。
如果波浪號字首是+,則~+被替換成當前工作目錄(pwd)
如果波浪號字首是-,則~-被替換成上乙個工作目錄(oldpwd)
如果波浪號字首是個數字n,則把~n替換成目錄堆疊(用dirs命令可以檢視目錄堆疊)的第n個元素(這個似乎沒什麼用)
[jjz@localhost ~]$ echo ~
/home/jjz
[jjz@localhost ~]$ echo /~
/~ 波浪號不是在token的開頭,不進行擴充套件
[jjz@localhost ~]$ echo ~root
/root
[jjz@localhost ~]$ echo ~root/
/root/
[jjz@localhost ~]$ echo ~+
/home/jjz 替換成 當前目錄
[jjz@localhost ~]$ echo ~-
~- 替換成上乙個目錄,因為我沒用過cd,上乙個目錄oldpwd沒有設定,所謂替換失敗,原樣輸出
[jjz@localhost ~]$ cd project
[jjz@localhost project]$ echo ~- 這個好了
/home/jjz
[jjz@localhost project]$
變數擴充套件
這個大家最熟悉了,$foo!$真是個好東西,變數擴充套件,命令替換,算術擴充套件都離不了它(當然還能買東西)。一般情況下我們習慣使用$var,其實正規的格式是$。前一種形式更簡便,後一種更強大,很多時候必須用後一種形式才行。
先說說間接引用,這東西很像c語言裡的指標。
$,就是左花括號後面緊跟乙個感嘆號。bash會把變數的值作為新的變數再求值。
[jjz@localhost project]$ a=b其他的操作還是列個表出來,看上去可能更清晰[jjz@localhost project]$ b=1
[jjz@localhost project]$ echo $
1
形式意義
$如果變數var已被設定且非空,則代入它的值,否則帶入word
$如果變數var已被設定且空,就帶入它的值,否則將var設為word並帶入var,位置參量不能用這種方式賦值。
$如果var已被設定且值非空,帶入word;否則什麼都不帶入(帶入空)
$如果var已被設定且值非空,就帶入它的值,否則列印word並退出shell。省略word會輸出:parameter null or not set
注意:上面word可以是乙個變數,使用$word的形式引用其值
$獲取var中offset開始的字串
$獲取var中offset開始長為length的字串。
注意:上面的offset和length可以使變數,使用$offset,$length引用其值
$替換為變數中字元個數,如果var是* ,@或陣列,長度則是位置參量的個數。
$把字串尾部與模式進行最小匹配,並刪除匹配到的部分。
$把字串尾部與模式進行最大匹配,並刪除匹配到的部分。
$把字串頭部與模式進行最小匹配,並刪除匹配到的部分。
$把字串頭部與模式進行最大匹配,並刪除匹配到的部分
$使用string替換pattern的最大匹配部分。如果pattern以/開頭則進行全部替換,否則只替換第乙個匹配的位置。如果pattern以#開始,則起始部分必須匹配,如果以%開始則結尾部分必須匹配
注意:
上面的pattern可以使變數,使用$pattern引用其值。
如果var是*、@或陣列且以下標為*或@的形式出現,則對其中每乙個元素都進行匹配操作。
命令替換
用命令的輸出來替換命令本身。有兩種形式$(cmd)和`cmd`,推薦前一種形式,後一種形式是old-style了。這個沒什麼好說的,很簡單。
算術擴充套件
用算術表示式的值替換算術表示式本身。格式$((expr))。expr是個表示式,如4+3。理解起來比較簡單。不過關於expression,bash有自己特定的支援,某些運算它是做不了的。
[jjz@localhost project]$ echo $((9+2))路徑擴充套件11[jjz@localhost project]$ b=2
[jjz@localhost project]$ echo $((4+b))
6[jjz@localhost project]$
shell掃瞄每個標記看看是否有*,?和,這三個就是進行路徑擴充套件的。如果某個標記裡出現了三者中的乙個或幾個,這個標記就被認為是乙個模式,shell會對當前目錄下的檔案列表按檔名排序並逐一與此模式進行比較,如果有匹配這個模式的檔案,shell用所有能匹配這個模式的檔名列表替換這個模式。如果沒有能匹配這個模式的檔案,shell原樣保留該模式。當然,shell提供了很多選項,定製匹配成功和失敗的處理,還可以選擇使用高階的正規表示式,這裡不進行討論,只說說shell的預設情況。此處的三個特殊字元也都比較簡單*匹配0到多個字元,?匹配乙個字元,匹配某個區間裡乙個字元。
shell中的命令替換和變數替換
可以用 command 也可以用 command 二者是有區別的,先看一下 command 注意 這裡不是引號,而反引號 下面這個是 command 變數替換可以根據變數的狀態 是否為空 是否定義等 來改變它的值,可以使用的變數替換形式 形式說明 變數本來的值 如果變數 var 為空或已被刪除 un...
shell的命令替換和命令組合
bash shell系列文章 linux中使用反引號 在波浪線的按鍵上 或者 來執行命令替換。使用括號 來組合一系列命令。root xuexi echo what date it is?date f what date it is?2016 09 25 root xuexi tmp echo wha...
shell命令的替換
shell 命令替換是指將命令的輸出結果賦值給某個變數。比如,在某個目錄中輸入 ls 命令可檢視當前目錄中所有的檔案。shell 中有兩種方式可以完成命令替換,一種是反引號,一種是 使用方法如下 variable commands variable commands 其中,variable 是變數名...