1. 程式人生 > >shell中的大括號和小括號

shell中的大括號和小括號

在這裡我想說的是幾種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 ab 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 '{printNR,$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 CST2005

$ echo${var:-$(date)}

日 3月 6 02:11:46 CST2005

$ 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*}

$