在這里我想說的是幾種shell里的小括號,大括號結構和有括號的變量,命令的用法,如下:
1.${var}?
2.$(cmd)?
3.()和{}?
4.${var:-string},${var:+string},${var:=string},${var:?string}?
5.$((exp))?
6.$(var%pattern),$(var%%pattern),$(var#pattern),$(var##pattern)??
現在分述如下:
1.Shell中變量的原形:${var}
大家常見的變量形式都是$var,如
$?var=test?
$?echo?$var?
test??
但當你要顯示變量值加隨意的字符(我這里用AA)時,就會出錯,如下:
$?echo?$varAA?
$??
這時應該用變量的原形:${var},即是加一個大括號來限定變量名稱的范圍,如下
$?echo?${var}AA?
testAA?
$??
以這個特性,我們可以很方便地寫一個批量改后綴名的程序,我把它命名為mymv,程序如下:
#!/bin/bash?
tail=$1?
for?filename?in?`ls`?
do?
mv?$filename?${filename}.$tail?
done??
程序需要提供一個后綴名,如c,表示改為后綴為c的C程序文件,看下面的測試:
$?ls?
a?b?c?
$?mymv?c?
$?ls?
a.c?b.c?c.c?
$??
看樣子程序運行的很好,但這是不完善的程序,有2個要注意的問題:
A,目錄下沒有子目錄,如果有一個目錄,假設為dir,則也會被改為dir.c,這顯然不是我們想要的,應該修正這個程序能識別目錄。
B,沒有幫助對程序的參數進行處理,程序應該足夠友好,在用戶沒有給定后綴名時應能處理,像上面的將直接給文件加上了一個點(.),這顯然也不是我們想要的。
因為我們的目的是說明${var},這樣已經足夠了,因此這里不會再對上面的程序進行修正。
2.命令替換$(cmd)
命令替換$(cmd)和符號`cmd`(注意這不是單引號,在美式鍵盤上,`是ESC下面的那個鍵)有相同之處
$?ls?
a?b?c?
$?echo?$(ls)?
a?b?c?
$?echo?`ls`?
a?b?c??
我們來分析一下命令echo $(ls),以便理解所謂命令替換是什么意思:
shell掃描一遍命令行,發現了$(cmd)結構,便將$(cmd)中的cmd執行一次,得到其標準輸出,再將此輸出放到原來命令echo $(ls)中的$(ls)位置,即替換了$(ls),再執行echo命令。
如下:
echo $(ls)被替換成了echo a b c
這里要注意的是$(cmd)中的命令的錯誤輸出是不會被替換的,替換的只是標準輸出:
$?var=$(cat?d)?????###文件d在當前目錄不存在?
cat:?d:?沒有那個文件或目錄?
$?echo?$var?
$???????###顯然var變量的值是空的??
3.一串的命令執行()和{}
()和{}都是對一串的命令進行執行,但有所區別:
A,()只是對一串命令重新開一個子shell進行執行
B,{}對一串命令在當前shell執行
C,()和{}都是把一串的命令放在括號里面,并且命令之間用;號隔開
D,()最后一個命令可以不用分號
E,{}最后一個命令要用分號
F,{}的第一個命令和左括號之間必須要有一個空格
G,()里的各命令不必和括號有空格
H,()和{}中括號里面的某個命令的重定向只影響該命令,但括號外的重定向則影響到括號里的所有命令
我們來看幾個例子:
$?var=test?
$?(var=notest;?echo?$var)???????###變量var值為notest,此是在子shell中有效?
notest?
$?echo?$var????????###父shell中值仍為test?
test?
$?{?var=notest;?echo?$var;}?????###注意左括號和var之間要有一個空格?
notest?
$?echo?$var?????????????????????###父shell中的var變量的值變為了notest?
notest?
$?{?var1=test1;var2=test2;echo?$var1>a;echo?$var2;}????###輸出test1被重定向到文件a中,?
test2????????????????###而test2輸出則仍輸出到標準輸出中。?
$?cat?a?
test1?
$?{?var1=test1;var2=test2;echo?$var1;echo?$var2;}>a?????????????###括號內命令的標準輸出全部被重定向到文件a中?
$?cat?a?
test1?
test2??
4,幾種特殊的替換結構:${var:-string},${var:+string},${var:=string},${var:?string}
A,${var:-string}和${var:=string}
若變量var為空,則用在命令行中用string來替換${var:-string},否則變量var不為空時,則用變量var的值來替換${var:-string}
如:
$?echo?newvar?
$?echo?${newvar:-a}?
a?
$?echo?newvar?????????????###變量newvar的值仍然是空,但上一命令行中${newvar:-a}被替換成了a?
$?newvar=b?
$?echo?${newvar:-a}???????###變量newvar的值不為空時,此命令行中的${newvar:-b}被替換為$newvar,即b?
b?
$??
對于${var:=string}的替換規則和${var:-string}是一樣的,所不同之處是${var:=string}若var為空時,用string替換${var:=string}的同時,把string賦給變量var:
$?echo?newvar?
$?echo?${newvar:=a}?
a?
$?echo?newvar???????????###變量newvar被賦值為a,同時${newvar:=a}被替換成a?
a?
$?echo?${newvar:=b}?????###變量newvar不為空(其值已被賦為a),則${newvar:=b}被替換為newvar的值(即b)?
a?
$?echo?$newvar?
a??
${var:=string}很常用的一種用法是,判斷某個變量是否賦值,沒有的話則給它賦上一個默認值。
如設置默認的編輯器:
echo?You?use?editor:?${EDITOR:=/bin/vi}??
B,${var:+string}
${var:+string}的替換規則和上面的相反,即只有當var不是空的時候才替換成string,若var為空時則不替換或者說是替換成變量 var的值,即空值。(因為變量var此時為空,所以這兩種說法是等價的)
$?echo?$newvar?
a?
$?echo?${newvar:+b}?
b?
$?echo?$newvar?
a?
$?newvar=?
$?echo?${newvar:+b}?
$??
C,${var:?string}
替換規則為:若變量var不為空,則用變量var的值來替換${var:?string};若變量var為空,則把string輸出到標準錯誤中,并從腳本中退出。我們可利用此特性來檢查是否設置了變量的值。
$?newvar=?
$?echo?${newvar:?沒有設置newvar的值}?
bash:?newvar:?沒有設置newvar的值?
$?newvar=a?
$?echo?${newvar:?沒有設置newvar的值}?
a?
$??
補充擴展:在上面這五種替換結構中string不一定是常值的,可用另外一個變量的值或是一種命令的輸出。
$?echo?${var:-`date`}?
日?3月?6?02:10:39?CST?2005?
$?echo?${var:-$(date)}?
日?3月?6?02:11:46?CST?2005?
$?a=test?
$?echo?${var:-$a}?
test?
$??
5.POSIX標準的擴展計算:$((exp))
這種計算是符合C語言的運算符,也就是說只要符合C的運算符都可用在$((exp)),甚至是三目運算符。
注意:這種擴展計算是整數型的計算,不支持浮點型.若是邏輯判斷,表達式exp為真則為1,假則為0。
$?echo?$((3+2))?
5?
$?echo?$((3>2))?
1?
$?echo?$((25<3???2:3))?
3?
$?echo?$var?
$?echo?$((var=2+3))?
5?
$?echo?$var?
5?
$?echo?$((var++))?
5?
$?echo?$var?
6?
$??
好了,上面的例子足夠了,這也表明了這種擴展運算是很強大的。
6.四種模式匹配替換結構:${var%pattern},${var%%pattern},${var#pattern},${var##pattern}
這四種結構的意義是:${var%pattern}和${var%%pattern}表示從最右邊(即結尾)匹配的,${var#pattern} 和${var##pattern}從最左邊(即開頭)匹配的。其中${var%pattern}和${var#pattern}是最短匹 配,${var%%pattern}和${var##pattern}是最長匹配。只有在pattern中使用了通配符才能有最長最短的匹配,否則沒有最 長最短匹配之分。
結構中的pattern支持通配符,*表示零個或多個任意字符,?表示零個或一個任意字符,[...]表示匹配中括號里面的字符,[!...]表示不匹配中括號里面的字符。
$?var=aabbbccbbdbb?
$?echo?${var%b}?
aabbbccbbdb?
$?echo?${var%%b}?
aabbbccbbdb?
$?echo?${var#a}?
abbbccbbdbb?
$?echo?${var##a}?
abbbccbbdbb?
$?echo?${var%*b}?
aabbbccbbdb?
$?echo?${var%%*b}?
$?echo?${var#a*}?
abbbccbbdbb?
$?echo?${var##a*}?
$??
上面是簡單的例舉四種模式匹配替換結構的用法。