標籤:
在這裡我想說的是幾種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
下面是一個腳步例子:
(
echo "1"
echo "2"
) | awk ‘{print NR,$0}‘
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}很常用的一種用法是,判斷某個變數是否賦值,沒有的話則給它賦上一個預設值。
如設定預設的編輯器:
PHP 代碼:
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*}
$
shell中${ } 的一些特異功能
假設我們定義了一個變數為:
file=/dir1/dir2/dir3/my.file.txt
我們可以用 ${ } 分別替換獲得不同的值:
${file#*/}:拿掉第一條 / 及其左邊的字串:dir1/dir2/dir3/my.file.txt
${file##*/}:拿掉最後一條 / 及其左邊的字串:my.file.txt
${file#*.}:拿掉第一個 . 及其左邊的字串:file.txt
${file##*.}:拿掉最後一個 . 及其左邊的字串:txt
${file%/*}:拿掉最後條 / 及其右邊的字串:/dir1/dir2/dir3
${file%%/*}:拿掉第一條 / 及其右邊的字串:(空值)
${file%.*}:拿掉最後一個 . 及其右邊的字串:/dir1/dir2/dir3/my.file
${file%%.*}:拿掉第一個 . 及其右邊的字串:/dir1/dir2/dir3/my
記憶的方法為:
# 是去掉左邊(在鑒盤上 # 在 $ 之左邊)
% 是去掉右邊(在鑒盤上 % 在 $ 之右邊)
單一符號是最小匹配﹔兩個符號是最大匹配。
${file:0:5}:提取最左邊的 5 個位元組:/dir1
${file:5:5}:提取第 5 個位元組右邊的連續 5 個位元組:/dir2
我們也可以對變數值裡的字串作替換:
${file/dir/path}:將第一個 dir 提換為 path:/path1/dir2/dir3/my.file.txt
${file//dir/path}:將全部 dir 提換為 path:/path1/path2/path3/my.file.txt
利用 ${ } 還可針對不同的變數狀態賦值(沒設定、空值、非空值):
${file-my.file.txt} :假如 $file 為空白值,則使用 my.file.txt 作預設值。(保留沒設定及非空值)
${file:-my.file.txt} :假如 $file 沒有設定或為空白值,則使用 my.file.txt 作預設值。 (保留非空值)
${file+my.file.txt} :不管 $file 為何值,均使用 my.file.txt 作預設值。 (不保留任何值)
${file:+my.file.txt} :除非 $file 為空白值,否則使用 my.file.txt 作預設值。 (保留空值)
${file=my.file.txt} :若 $file 沒設定,則使用 my.file.txt 作預設值,同時將 $file 定義為非空值。 (保留空值及非空值)
${file:=my.file.txt} :若 $file 沒設定或為空白值,則使用 my.file.txt 作預設值,同時將 $file 定義為非空值。 (保留非空值)
${file?my.file.txt} :若 $file 沒設定,則將 my.file.txt 輸出至 STDERR。 (保留空值及非空值))
${file:?my.file.txt} :若 $file 沒設定或為空白值,則將 my.file.txt 輸出至 STDERR。 (保留非空值)
還有,${#var} 可計算出變數值的長度:
${#file} 可得到 27 ,因為 /dir1/dir2/dir3/my.file.txt 剛好是 27 個位元組...
文章摘自:http://blog.sina.com.cn/s/blog_4a2a29f00100o2os.html 謝謝博友分享O(∩_∩)O~
shell中的大括弧和小括弧