我們上一章介紹了()與{}的不同,這次讓我們擴(kuò)展一下,看看更多的變化:$()與${}又是啥玩意兒呢?
在bash shell中, $()與``(反引號(hào))都是用來(lái)做命令替換(command substitution)的。
所謂的命令替換與我們第五章學(xué)過(guò)的變量替換差不多,都是用來(lái)重組命令行:完成 `` 或者$()里面的
命令,將其結(jié)果替換出來(lái),再重組命令行。
例如:
$ echo the last sunday is $(date -d "last sunday" +%Y-%m-%d)
如此便可方便得到上一個(gè)星期天的日期了...^_^
在操作上, 用$()或``都無(wú)所謂, 只是我個(gè)人比較喜歡用$(),理由是:
``(反引號(hào))很容易與''(單引號(hào))搞混亂,尤其對(duì)初學(xué)者來(lái)說(shuō)。 有時(shí)在一些奇怪的字形顯示中,兩種符號(hào)是一模一樣的(只取兩點(diǎn))。 當(dāng)然了有經(jīng)驗(yàn)的朋友還是一眼就能分辨兩者。只是,若能更好的避免混亂, 又何樂(lè)而不為呢? ^_^
command1 `command2 `command3` `
原來(lái)的本意是要在command2 `command3` , 先將command3替換出來(lái)給command2處理, 然后再將command2的處理結(jié)果,給command1來(lái)處理。 然而真正的結(jié)果在命令行中卻是分成了`command2`與 ``。
正確的輸入應(yīng)該如下:
command1 `command2 \`command3\` `
要不然換成$()就沒(méi)有問(wèn)題了:
command1 $(commmand2 $(command3))
只要你喜歡,做多少層的替換都沒(méi)有問(wèn)題~~~^_^
不過(guò),$()并不是沒(méi)有弊端的... 首先,``基本上可用在所有的unix shell中使用, 若寫成 shell script,其移植性比較高。 而$()并不是每一種shell都能使用,我只能說(shuō), 若你用bash2的話,肯定沒(méi)問(wèn)題... ^_^
接下來(lái),再讓我們看看${}吧...它其實(shí)就是用來(lái)做 變量替換用的啦。 一般情況下,$var與${var}并沒(méi)有啥不一樣。 但是用${}會(huì)比較精準(zhǔn)的界定變量名稱的范圍, 比方說(shuō):
$ A=B
$ echo $AB
原本是打算先將$A的結(jié)果替換出來(lái), 然后在其后補(bǔ)一個(gè)字母B; 但命令行上, 真正的結(jié)果卻是替換變量名稱為AB的值出來(lái)... 若使用${}就沒(méi)有問(wèn)題了:
$ A=B
$ echo ${A}B
$ BB
不過(guò),假如你只看到${}只能用來(lái)界定變量名稱的話,
那你就實(shí)在太小看bash了。
為了完整起見(jiàn),我這里再用一些例子加以說(shuō)明${}的一些
特異功能:
假設(shè)我們定義了一個(gè)變量file為:
file=/dir1/dir2/dir3/my.file.txt
我們可以用${}分別替換獲得不同的值:
${file#*/} #其值為:dir1/dir2/dir3/my.file.txt
拿掉第一個(gè)/及其左邊的字符串,其結(jié)果為:
dir1/dir2/dir3/my.file.txt 。
${file#*.} #其值為:file.txt
拿掉第一個(gè).及其左邊的字符串,其結(jié)果為:
file.txt 。
${file##*/} #其值為:my.file.txt
拿掉最后一個(gè)/及其左邊的字符串,其結(jié)果為:
my.file.txt
${file##*.} #其值為:txt
拿掉最后一個(gè).及其左邊的字符串,其結(jié)果為:
txt
${file%/*} #其值為:/dir1/dir2/dir3
拿掉最后一個(gè)/及其右邊的字符串,其結(jié)果為:
/dir1/dir2/dir3。
${file%.*} #其值為:/dir1/dir2/dir3/my.file
拿掉最后一個(gè).及其右邊的字符串,其結(jié)果為:
/dir1/dir2/dir3/my.file。
${file%%/*} #其值為:其值為空。
拿掉第一個(gè)/及其右邊的字符串,其結(jié)果為:
空串。
${file%%.*} #其值為:/dir1/dir2/dir3/my。
拿掉第一個(gè).及其右邊的字符串,其結(jié)果為:
/dir1/dir2/dir3/my。
Tips:
記憶方法:
#是去掉左邊(在鍵盤上#在$的左邊);
%是去掉右邊(在鍵盤上%在$的右邊);單個(gè)符號(hào)是最小匹配;
兩個(gè)符號(hào)是最大匹配;
${file:0:5} #提取最左邊的5個(gè)字符:/dir1
${file:5:5} #提取第5個(gè)字符及其右邊的5個(gè)字符:/dir2
shell 字符串取子串的格式:${s:pos:length},
取字符串 s 的子串:從 pos 位置開(kāi)始的字符(包括該字符)的長(zhǎng)度為 length 的的子串;
其中pos為子串的首字符,在 s 中位置;
length為子串的長(zhǎng)度;
Note: 字符串中字符的起始編號(hào)為0.
${file/dir/path} #將第一個(gè)dir替換為path:/path1/dir2/dir3/my.file.txt
${file//dir/path} #將全部的dir替換為path:/path1/path2/path3/my.file.txt
shell 字符串變量值的替換格式:
首次替換:
${s/src_pattern/dst_pattern} 將字符串s中的第一個(gè)src_pattern替換為dst_pattern。
${s//src_pattern/dst_pattern} 將字符串s中的所有出現(xiàn)的src_pattern替換為dst_pattern.${file-my.file.txt} #如果file沒(méi)有設(shè)定,則使用
使用my.file.txt作為返回值, 否則返回${file};(空值及非空值時(shí),不作處理。);
${file:-my.file.txt} #如果file沒(méi)有設(shè)定或者${file}為空值, 均使用my.file.txt作為其返回值,否則,返回${file}.(${file} 為非空值時(shí),不作處理);
${file+my.file.txt} #如果file已設(shè)定(為空值或非空值), 則使用my.file.txt作為其返回值,否則不作處理。(未設(shè)定時(shí),不作處理);
${file:+my.file.txt} #如果${file}為非空值, 則使用my.file.txt作為其返回值,否則,(未設(shè)定或者為空值時(shí))不作處理。
${file=my.file.txt} #如果file為設(shè)定,則將file賦值為my.file.txt,同時(shí)將${file}作為其返回值;否則,file已設(shè)定(為空值或非空值),則返回${file}。
${file:=my.file.txt} #如果file未設(shè)定或者${file}為空值, 則my.file.txt作為其返回值,
同時(shí),將${file}賦值為my.file.txt,否則,(非空值時(shí))不作處理。
${file?my.file.txt} #如果file沒(méi)有設(shè)定,則將my.file.txt輸出至STDERR, 否側(cè),
已設(shè)定(空值與非空值時(shí)),不作處理。
${file:?my.file.txt} #若果file未設(shè)定或者為空值,則將my.file.txt輸出至STDERR,否則,
非空值時(shí),不作任何處理。Tips:
以上的理解在于,你一定要分清楚,
unset與null以及non-null這三種狀態(tài)的賦值; 一般而言,與null有關(guān),若不帶:, null不受影響; 若帶:, 則連null值也受影響。
${#var} ${#file} #其值為27, 因?yàn)?dir1/dir2/dir3/my.file.txt剛好為27個(gè)字符。
接下來(lái),為大家介紹一下bash的數(shù)組(array)的處理方法。
一般而言, A="a b c def"
這樣的變量只是將$A替換為一個(gè)字符串,
但是改為 A=(a b c def),
則是將$A定義為數(shù)組....
${A[@]} #方法一
${A[*]} #方法二
以上兩種方法均可以得到:a b c def, 即數(shù)組的全部元素。
${A[0]}
其中,${A[0]}可得到a, 即數(shù)組A的第一個(gè)元素,
而 ${A[1]}則為數(shù)組A的第二元素,依次類推。
${#A[@]} #方法一
${#A[*]} #方法二
以上兩種方法均可以得到數(shù)組的長(zhǎng)度: 4, 即數(shù)組的所有元素的個(gè)數(shù)。
回憶一下,針對(duì)字符串的長(zhǎng)度計(jì)算,使用${#str_var};
我們同樣可以將該方法應(yīng)用于數(shù)組的成員:
${#A[0]}
其中,${#A[0]}可以得到:1,即數(shù)組A的第一個(gè)元素(a)的長(zhǎng)度;
同理,${#A[3]}可以得到: 3, 即數(shù)組A的第4個(gè)元素(def)的長(zhǎng)度。
A[3]=xyz
將數(shù)組A的第四個(gè)元素重新定義為 xyz。
Tips:
諸如此類的...
能夠善用bash的$()與${}可以大大提高及 簡(jiǎn)化shell在變量上的處理能力哦~~~^_^
好了,最后為大家介紹$(())的用途吧:
$(())是用來(lái)作整數(shù)運(yùn)算的。
在bash中, $(())的整數(shù)運(yùn)算符號(hào)大致有這些:
例如:
$ a=5; b=7; c=2;
$ echo $(( a + b * c ))
19
$ echo $(( (a + b)/c ))
6
$ echo $(( (a * b) % c ))
1
在$(())中的變量名稱,
可以在其前面加 $符號(hào)來(lái)替換,
也可以不用,如:
$(( $a + $b * $c )) 也可以得到19的結(jié)果。
此外,$(())還可作不同進(jìn)制(如二進(jìn)制、八進(jìn)制、十六進(jìn)制)的運(yùn)算,
只是輸出結(jié)果均為十進(jìn)制的。
echo $(( 16#2a )) #輸出結(jié)果為:42,(16進(jìn)制的2a)
以一個(gè)實(shí)用的例子來(lái)看看吧 : 假如當(dāng)前的umask是022,那么新建文件的權(quán)限即為:
$ umask 022
$ echo "obase=8; $(( 8#666 & (8#777 ^ 8#$(umask)) ))" | bc
644
事實(shí)上,單純用(())也可以重定義變量值,或作 testing:
a=5; ((a++)) #可將$a 重定義為6
a=5; ((a--)) #可將$a 重定義為4
a=5; b=7; ((a< b)) #會(huì)得到0 (true)返回值。
常見(jiàn)的用于(())的測(cè)試符號(hào)有如下這些:
| 符號(hào) | 符號(hào)名稱 |
|---|---|
| < | 小于號(hào) |
| > | 大于號(hào) |
| <= | 小于或等于 |
| >= | 大于或等于 |
| == | 等于 |
| != | 不等于 |
Note:
使用
(())作整數(shù)測(cè)試時(shí), 請(qǐng)不要跟[]的整數(shù)測(cè)試搞混亂了。更多的測(cè)試,我們將于第10章為大家介紹。
怎樣? 好玩吧... ^_^
okay,這次暫時(shí)說(shuō)這么多...
上面的介紹,并沒(méi)有詳列每一種可用的狀態(tài), 更多的,就請(qǐng)讀者參考手冊(cè)文件(man)吧...