一、小括號,園括號()
1、單小括號 ()
2、雙小括號 (( ))
- if ($i<5)
- if [ $i -lt 5 ]
- if [ $a -ne 1 -a $a != 2 ]
- if [ $a -ne 1] && [ $a != 2 ]
- if [[ $a != 1 && $a != 2 ]]
- for i in $(seq 0 4);do echo $i;done
- for i in `seq 0 4`;do echo $i;done
- for ((i=0;i<5;i++));do echo $i;done
- for i in {0..4};do echo $i;done
二)中括號,方括號[]
1、單中括號 []
2、雙中括號[[ ]]
三)大括號、花括號 {}
1、常規用法。
- bogon:/home/bash # ls {ex1,ex2}.sh
- ex1.sh ex2.sh
- bogon:/home/bash # ls {ex{1..3},ex4}.sh
- ex1.sh ex2.sh ex3.sh ex4.sh
- bogon:/home/bash # ls {ex[1-3],ex4}.sh
- ex1.sh ex2.sh ex3.sh ex4.sh
2)幾種特殊的替換結構:${var:-string},${var:+string},${var:=string},${var:?string}
B. ${var:+string}的替換規則和上面的相反,即只有當var不是空的時候才替換成string,若var為空時則不替換或者說是替換成變量 var的值,即空值。(因為變量var此時為空,所以這兩種說法是等價的)
C,${var:?string}替換規則為:若變量var不為空,則用變量var的值來替換${var:?string};若變量var為空,則把string輸出到標准錯誤中,並從腳本中退出。我們可利用此特性來檢查是否設置了變量的值。
補充擴展:在上面這五種替換結構中string不一定是常值的,可用另外一個變量的值或是一種命令的輸出。
3)四種模式匹配替換結構:${var%pattern},${var%%pattern},${var#pattern},${var##pattern}
第一種模式:${variable%pattern},這種模式時,shell在variable中查找,看它是否一給的模式pattern結尾,如果是,就從命令行把variable中的內容去掉右邊最短的匹配模式第二種模式: ${variable%%pattern},這種模式時,shell在variable中查找,看它是否一給的模式pattern結尾,如果是,就從命令行把variable中的內容去掉右邊最長的匹配模式
第三種模式:${variable#pattern} 這種模式時,shell在variable中查找,看它是否一給的模式pattern開始,如果是,就從命令行把variable中的內容去掉左邊最短的匹配模式
第四種模式: ${variable##pattern} 這種模式時,shell在variable中查找,看它是否一給的模式pattern結尾,如果是,就從命令行把variable中的內容去掉右邊最長的匹配模式
這四種模式中都不會改變variable的值,其中,只有在pattern中使用了*匹配符號時,%和%%,#和##才有區別。結構中的pattern 支持通配符,*表示零個或多個任意字符,?表示零個或一個任意字符,[...]表示匹配中括號里面的字符,[!...]表示不匹配中括號里面的字符
- bogon:/home/bash # var=testcase
- bogon:/home/bash # echo $var
- testcase
- bogon:/home/bash # echo ${var%s*e}
- testca
- bogon:/home/bash # echo $var
- testcase
- bogon:/home/bash # echo ${var%%s*e}
- te
- bogon:/home/bash # echo ${var#?e}
- stcase
- bogon:/home/bash # echo ${var##?e}
- stcase
- bogon:/home/bash # echo ${var##*e}
- bogon:/home/bash # echo ${var##*s}
- e
- bogon:/home/bash # echo ${var##test}
- case
()
命令組.在括號中的命令列表, 將會作為一個子shell來運行.
在括號中的變量,由於是在子shell中,所以對於腳本剩下的部分是不可用的. 父進程, 也就是腳本本身, 將不能夠讀取在子進程中創建的變量, 也就是在子shell中創建的變量.
(cmd1;cmd2;cmd3)
初始化數組.
Array=(element1 element2 element3)
$(...)
相當於`...`命令,返回括號中命令執行的結果
let命令
(( ))
(( ... ))結構可以用來計算並測試算術表達式的結果. 退出狀態將會與[ ... ]結構完全相反!還可應用到c風格的for,while循環語句,(( )) 中,所有的變量(加不加$無所謂)都是數值。
$((...))結構的表達式是C風格的表達式,其返回的結果是表達式值,其中變量引用可不用‘$’(當然也可以)
for((...;...;...))
do
cmd
done
while ((...))
do
cmd
done
比較操作符
<
小於
(("$a" < "$b"))
<=
小於等於
(("$a" <= "$b"))
>
大於
(("$a" > "$b"))
>=
大於等於
(("$a" >= "$b"))
(( 0 ))
echo "Exit status of \"(( 0 ))\" is $?." # 1
(( 1 ))
echo "Exit status of \"(( 1 ))\" is $?." # 0
(( 5 > 4 )) # 真
echo "Exit status of \"(( 5 > 4 ))\" is $?." # 0
(( 5 > 9 )) # 假
echo "Exit status of \"(( 5 > 9 ))\" is $?." # 1
(( 5 - 5 )) # 0
echo "Exit status of \"(( 5 - 5 ))\" is $?." # 1
(( 5 / 4 )) # 除法也可以.
echo "Exit status of \"(( 5 / 4 ))\" is $?." # 0
(( 1 / 2 )) # 除法的計算結果 < 1.
echo "Exit status of \"(( 1 / 2 ))\" is $?." # 截取之后的結果為 0.
# 1
(( 1 / 0 )) 2>/dev/null # 除數為0, 非法計算.
#
echo "Exit status of \"(( 1 / 0 ))\" is $?." # 1
for ((a=1; a <= LIMIT ; a++)) # 雙圓括號, 並且"LIMIT"變量前面沒有"$".
do
echo -n "$a "
done
while (( a <= LIMIT )) # 雙圓括號, 變量前邊沒有"$".
do
echo -n "$a "
((a += 1)) # let "a+=1"
done
a=2
b=$(($a*4)) #a=2 b=8
c=$((a*3)) #a=2 c=6
[ ]
條件測試表達式放在[ ]中. 值得注意的是[是shell內建test命令的一部分, 並不是/usr/bin/test中的外部命令的一個鏈接.
文件測試操作符(如果下面的條件成立將會返回真)
-e
文件存在(推薦用)
-a
文件存在(不推薦用)
-f
表示這個文件是一個一般文件(並不是目錄或者設備文件)
-s
文件大小不為零
-d
表示這是一個目錄
-b
表示這是一個塊設備(軟盤, 光驅, 等等.)
-c
表示這是一個字符設備(鍵盤, modem, 聲卡, 等等.)
-p
這個文件是一個管道
-h
這是一個符號鏈接
-L
這是一個符號鏈接
-S
表示這是一個socket
-t
文件(描述符)被關聯到一個終端設備上
這個測試選項一般被用來檢測腳本中的stdin([ -t 0 ]) 或者stdout([ -t 1 ])是否來自於一個終端.
-r
文件是否具有可讀權限(指的是正在運行這個測試命令的用戶是否具有讀權限)
-w
文件是否具有可寫權限(指的是正在運行這個測試命令的用戶是否具有寫權限)
-x
文件是否具有可執行權限(指的是正在運行這個測試命令的用戶是否具有可執行權限)
-g
set-group-id(sgid)標記被設置到文件或目錄上
如果目錄具有sgid標記的話, 那么在這個目錄下所創建的文件將屬於擁有這個目錄的用戶組, 而不必是創建這個文件的用戶組. 這個特性對於在一個工作組中共享目錄非常有用.
-u
set-user-id (suid)標記被設置到文件上
如果一個root用戶所擁有的二進制可執行文件設置了set-user-id標記位的話, 那么普通用戶也會以root權限來運行這個文件. [1] 這對於需要訪問系統硬件的執行程序(比如pppd和cdrecord)非常有用. 如果沒有suid標志的話, 這些二進制執行程序是不能夠被非root用戶調用的.
-rwsr-xr-t 1 root 178236 Oct 2 2000 /usr/sbin/pppd
對於設置了suid標志的文件, 在它的權限列中將會以s表示.
-k
設置粘貼位
對於"粘貼位"的一般了解, save-text-mode標志是一個文件權限的特殊類型. 如果文件設置了這個標志, 那么這個文件將會被保存到緩存中, 這樣可以提高訪問速度. [2] 粘貼位如果設置在目錄中, 那么它將限制寫權限. 對於設置了粘貼位的文件或目錄, 在它們的權限標記列中將會顯示t.
drwxrwxrwt 7 root 1024 May 19 21:26 tmp/
如果用戶並不擁有這個設置了粘貼位的目錄, 但是他在這個目錄下具有寫權限, 那么這個用戶只能在這個目錄下刪除自己所擁有的文件. 這將有效的防止用戶在一個公共目錄中不慎覆蓋或者刪除別人的文件. 比如說/tmp目錄. (當然, 目錄的所有者或者root用戶可以隨意刪除或重命名其中的文件.)
-O
判斷你是否是文件的擁有者
-G
文件的group-id是否與你的相同
-N
從文件上一次被讀取到現在為止, 文件是否被修改過
f1 -nt f2
文件f1比文件f2新
f1 -ot f2
文件f1比文件f2舊
f1 -ef f2
文件f1和文件f2是相同文件的硬鏈接
!
"非" -- 反轉上邊所有測試的結果(如果沒給出條件, 那么返回真).
比較操作符
整數比較
-eq
等於
-ne
不等於
-gt
大於
-ge
大於等於
-lt
小於
-le
小於等於
字符串比較
=
等於
==
等於,與=等價.(==比較操作符在雙中括號對和單中括號對中的行為是不同的)
[[ $a == z* ]] # 如果$a以"z"開頭(模式匹配)那么結果將為真
[[ $a == "z*" ]] # 如果$a與z*相等(就是字面意思完全一樣), 那么結果為真.
[ $a == z* ] # 文件擴展匹配(file globbing)和單詞分割有效.
[ "$a" == "z*" ] # 如果$a與z*相等(就是字面意思完全一樣), 那么結果為真.
!=
不等號(這個操作符將在[[ ... ]]結構中使用模式匹配)
<
小於, 按照ASCII字符進行排序(注意"<"使用在[ ]結構中的時候需要被轉義)
>
大於, 按照ASCII字符進行排序(注意">"使用在[ ]結構中的時候需要被轉義)
-z
字符串為"null", 意思就是字符串長度為零
-n
字符串不為"null".
-a
邏輯與
-o
邏輯或
{xxx,yyy,zzz,...}
大括號擴展.
echo {1..20}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
cat {file1,file2,file3} > combined_file
# 把file1, file2, file3連接在一起, 並且重定向到combined_file中.
cp file22.{txt,backup}
# 拷貝"file22.txt"到"file22.backup"中
在大括號中, 不允許有空白, 除非這個空白被引用或轉義.
echo {file1,file2}\ :{\ A," B",' C'}
file1 : A file1 : B file1 : C file2 : A file2 : B file2 : C
代碼塊
這個結構事實上創建了一個匿名函數(一個沒有名字的函數). 然而, 與"標准"函數不同的是, 在其中聲明的變量,對於腳本其他部分的代碼來說還是可見的(除了用declare,typeset命令聲明的變量)
()會開啟一個新的子shell,{}不會開啟一個新的子shell
(())常用於算術運算比較,[[]]常用於字符串的比較.
$()返回括號中命令執行的結果
$(())返回的結果是括號中表達式值
${ }參數替換與擴展
參數替換
${var}
${var}=$var
${var:-default} ${var-default}
如果var未set,那么就是用default.兩者之間不同只有當var為空變量時,前者為default,后者為空.
${var:=default} ${var=default}
如果var未set,那么就設置default.兩者之間不同只有當var為空變量時,前者設置為default,后者設置為空.
${var:+default} ${var+default}
如果var被set,就是用default.未set,就使用null字符串.兩者之間不同只有當var為空變量時,前者為null字符串,后者為default.
上面三種參數替換中,第二種使用后變量的值被改變.
參數替換擴展
${#var} ${#array}
字符串長度或數組第一個元素的字符串長度
例外:
${#*}、${#@}指位置參數的個數.
${#array},$[#array[@]}指數組元素的個數
${var#pattern} ${var##pattern}
從var開頭刪除最近或最遠匹配pattern的子串.
${var%pattern} ${var%%pattern}
從var結尾刪除最近或最遠匹配pattern的子串.
${var:pos}
變量var從位置pos開始擴展.
${var:pos:len}
從位置pos開始,並擴展len長度個字符
${var/pattern/replacement} ${var//pattern/replacement}
使用replacement來替換var中的第一個或所有pattern的匹配.
${var/#pattern/replacement}
如果var的前綴匹配到了pattern,那么就用replacement來替換pattern.
${var/%pattern/replacement}
如果var的后綴匹配到了pattern,那么就用replacement來替換pattern.
${!varprefix*} ${!varprefix@}
前邊所有聲明過的,以varprefix為前綴的變量名.
[[]]就是條件表達式,在bash中,字符串比較用 > < != == <= >= 只是在[]中 < >需要轉義;對於數值比較.用 -lt -le -eq -ge -gt 來比較,與[[]]中表達不太一樣,在[ ] 中的 < > 需要用轉義 \< \>,如果有多個表達式,在[[ ]] 中用 && || 來組合,而[] 中是用 -a -o 來組合
1.() 符號
a.()會開啟一個新的子shell,{}不會開啟一個新的子shell
b.在括號中的變量,由於是在子shell中,所以對於腳本剩下的部分是不可用的. 父進程, 也就是腳本本身, 將不能夠讀取在子進程中創建的變量, 也就是在子shell中創建的變量.
c.$(...) 執行括號的內容,並返回結果,相當於`...`命令
d.(())常用於算術運算比較,[[]]常用於字符串的比較.
2.[ ]符號
a.條件測試表達式放在[ ]中. 值得注意的是[是shell內建test命令的一部分, 並不是/usr/bin/test中的外部命令的一個鏈接.
b.文件存在 -e ,-a
c.表示這個文件是一個一般文件 -f
d.文件大小不為零 -s
e.表示這是一個目錄 -d
f.表示這是一個塊設備(軟盤, 光驅, 等等.) -b
g.表示這是一個字符設備(鍵盤, modem, 聲卡, 等等.) -c
h.這個文件是一個管道 -p
i.這是一個符號鏈接 -h
j.這是一個符號鏈接-L
k.-S 表示這是一個socket
l.-t 文件(描述符)被關聯到一個終端設備上,這個測試選項一般被用來檢測腳本中的stdin([ -t 0 ]) 或者stdout([ -t 1 ])是否來自於一個終端.
m.-r 文件是否具有可讀權限(指的是正在運行這個測試命令的用戶是否具有讀權限)
n.-w 文件是否具有可寫權限(指的是正在運行這個測試命令的用戶是否具有寫權限)
o. -x 文件是否具有可執行權限(指的是正在運行這個測試命令的用戶是否具有可執行權限)
3.{}符號
${ }參數替換與擴展
