1、小括號、圓括號()
1.1 單小括號()
用途
|
|
|
---|---|---|
命令組 |
|
22 shell組命令與子進程 |
命令替換 |
|
3shell命令替換 |
初始化數組 | 如array=(a b c d) | 5shell中的數組 |
1.2 雙小括號(())
- 整數擴展。這種擴展計算是整數型的計算,不支持浮點型。((exp))結構擴展並計算一個算術表達式的值,如果表達式的結果為0,那么返回的退出狀態碼為1,或者是"假",而一個非零值的表達式所返回的退出狀態碼將為0,或者是"true"。若是邏輯判斷,表達式exp為真則為1,假則為0。
- 只要括號中的運算符、表達式符合C語言運算規則,都可用在$((exp))中,甚至是三目運算符。作不同進位(如二進制、八進制、十六進制)運算時,輸出結果全都自動轉化成了十進制。如:echo $((16#5f)) 結果為95,(16進位轉十進制)
- 單純用 (( )) 也可重定義變量值,比如 a=5; ((a++)) 可將 $a 重定義為6.
- 常用於算術運算比較,雙括號中的變量可以不使用符號前綴。括號內支持多個表達式用逗號分開。只要括號中的表達式符合C語言運算規則,比如可以直接使用for((i=0;i<5;i++)),如果不使用雙括號,則為for i in seq 0 4或者for i in 0..4。再如可以直接使用if ((i<5)), 如果不使用雙括號,則為if [ $i -lt 5 ]。
1.3 簡單測試
命令
|
結果
|
知識點
|
---|---|---|
for ((i=0;i<5;i++));do echo -n $i;done |
01234 |
echo 加上-n參數可以使數據字符串后不再換行 |
for i in $(seq 0 4);do echo -n $i;done |
01234 | |
for i in `seq 0 4`;do echo -n $i;done |
||
for i in {0..4};do echo -n $i;done |
2、中括號、方括號[]
2.1 單中括號[]
- bash 的內部命令,[]和test是等同的。這個命令把它的參數作為比較表達式或者作為文件測試,並且根據比較的結果來返回一個退出狀態碼。
- test和[] 10 shell test命令
- 字符范圍。用作正則表達式的一部分,描述一個匹配的字符范圍。作為test用途的中括號內不能使用正則。
- 在一個array 結構的上下文中,中括號用來引用數組中每個元素的編號。
2.2 雙中括號[[]]
- [[]]是 bash 程序語言的關鍵字。並不是一個命令,[[ ]] 結構比[ ]結構更加通用。在[[和]]之間所有的字符都不會發生文件名擴展或者單詞分割,但是會發生參數擴展和命令替換。
- 支持字符串的模式匹配,使用=~操作符時甚至支持shell的正則表達式。字符串比較時可以把右邊的作為一個模式,而不僅僅是一個字符串,比如[[ hello == hell? ]],結果為真。[[ ]] 中匹配字符串或通配符,不需要引號。
- 使用[[ … ]]條件判斷結構,而不是[ … ],能夠防止腳本中的許多邏輯錯誤。比如,&&、||、<和> 操作符能夠正常存在於[[ ]]條件判斷結構中,但是如果出現在[ ]結構中的話,會報錯。比如可以直接使用if [[ $a !=1 && $a != 2 ]], 如果不適用雙括號, 則為if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。
- bash把雙中括號中的表達式看作一個單獨的元素,並返回一個退出狀態碼。
2.3 簡單測試
[[ 2 lt 3 ]] && echo true | true |
[[ 2 \< 3 ]] && echo true | bash: 期待二元條件運算符 bash: `\<' 附近有語法錯誤 |
[ 2 \< 3 ] && echo true | true |
[ 2 < 3 ] && echo true | bash: 3: 沒有那個文件或目錄 |
3、大括號、花括號{}
3.1常規用法
1.花括號拓展。(通配(globbing))將對花括號中的文件名做擴展。在大括號中,不允許有空白,除非這個空白被引用或轉義。
-
- 對大括號中的以逗號分割的文件列表進行拓展。如touch {a,b}.txt 結果為a.txt b.txt。
- 對大括號中以點點()分割的順序文件列表起拓展作用,如:touch {a..d}.txt 結果為a.txt b.txt c.txt d.txt。
2.代碼塊,又被稱為內部組,這個結構事實上創建了一個匿名函數 。與小括號中的命令不同,花括號內的命令不會新開一個子shell運行,即腳本余下部分仍可使用括號內變量。括號內的命令間用分號隔開,最后一個也必須有分號。{}的第一個命令和左括號之間必須要有一個空格。
3.2 幾種特殊的替換結構
命令 | 替換規則 | 舉栗 | 注意點 |
---|---|---|---|
$ {var:-string} | 若變量var為空,則用在命令行中用string來替換{var:−string},var的值不變 變量var不為空時,則用變量var的值來替換{var:-string},var的值不變 |
|
${var:−string}的值會變化,但是${var}的值沒有變化 |
$ {var:=string} | 當var為空時,string會賦給var與{var:−string},var的值變化 當var不為空時,會用變量var的值來替換{var:−string} 與上述原則不同的是當var為空時,var會被賦值,很常用的一種用法是,判斷某個變量是否賦值,沒有的話則給它賦上一個默認值 |
|
若變量var為空,則{var:=string}與{var}的值都會被賦值為string 若變量var不為空,則{var:=string}與{var}的值都還為var |
$ {var:+string} | 替換規則與第一種完全相反 當var不為空時用string來替換{var:−string},若var為空時則不替換 不管var是否為空,${var}的值都不會發生變化 |
a=2 echo ${a:+44} #result is 44 echo ${a} #result is 2 echo ${c} #result is empty echo ${c:+44} #result is empty echo ${c} #result is empty |
|
$ {var:?string} | 若變量var不為空,則用變量var的值來替換${var:?string}; 若變量var為空,則把string輸出到標准錯誤中,並從腳本中退出。 我們可利用此特性來檢查是否設置了變量的值。 |
#!/bin/bash var=4 echo '${var:?33}: '${var:?33} echo '${s:?33}: '${s:?33} echo 'aaaaaaaaaaaa' |
執行:bash test1.sh 2>result.h 結果:${var:?33}: 4 執行: cat result.h 結果:test1.sh: line 4: s: 33 當var為空時,會從腳本中退出,所以沒有打印aaaaaaaaaaaa |
tips:在上面替換結構中string不一定是常值的,可用另外一個變量的值或是一種命令的輸出。 |
3.3 四種模式匹配替換結構
字符串的截取:2shell中處理字符串
3.4 字符串的提取和替換
4、$符號后面的括號()
- ${a} 變量a的值, 在不引起歧義的情況下可以省略大括號。
- (cmd)命令替換,和cmd效果相同,結果為shell命令cmd的輸出,不過某些Shell版本不支持()形式的命令替換, 如tcsh。
- $((expression)) 和 expr expression 效果相同, 計算數學表達式expr的數值。 其中expr只要符合C語言的運算規則即可, 甚至三目運算符和邏輯表達式都可以計算。
5、使用注意
單小括號,(cmd1;cmd2;cmd3) 新開一個子shell順序執行命令cmd1,cmd2,cmd3, 各命令之間用分號隔開, 最后一個命令后可以沒有分號。
單花括號,{ cmd1;cmd2;cmd3;} 在當前shell順序執行命令,cmd1,cmd2,cmd3, 各命令之間用分號隔開, 最后一個命令后必須有分號,第一條命令和左括號之間必須用空格隔開。
對{}和()而言, 括號中的重定向符只影響該條命令,而括號外的重定向符影響到括號中的所有命令
0.[[]] [] (())的對比
[[ ]] 對數字的比較不友好,所以使用 if 判斷條件時,建議用(())來處理整型數字,用[[]]來處理字符串或者文件。
|
用法
|
說明
|
腳本
|
支持邏輯運算符
|
||||||
---|---|---|---|---|---|---|---|---|---|---|
(()) | ((expression)) 不需要注意空格 |
|
((a>7 && b==c)) | |||||||
test/[] | test expression 或[ expression ] 注意空格 |
|
|
|
||||||
[[]] [[ ]] 是 test 的升級版,對細節進行了優化,並且擴展了一些功能 |
[[ expression ]] 注意空格 |
|
|
[[ ]] 剔除了 test 命令的
|