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

$ echo $newvar ###變量newvar的值仍然是空,但上一命令行中${newvar:-a}被替換成了a

$ newvar=b 
$ echo ${newvar:-a} ###變量newvar的值不爲空時,此命令行中的${newvar:-b}被替換爲$newvar,即b 

$

對於${var:=string}的替換規則和${var:-string}是一樣的,所不同之處是${var:=string}若var爲空時,用string替換${var:=string}的同時,把string賦給變量var:


$ echo $newvar

$ echo ${newvar:=a} 

$ echo $newvar ###變量newvar被賦值爲a,同時${newvar:=a}被替換成a 

$ echo ${newvar:=b} ###變量newvar不爲空(其值已被賦爲a),則${newvar:=b}被替換爲newvar的值(即b) 

$ 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 

$ echo ${newvar:+b} 

$ echo $newvar 

$ 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的值} 

$

補充擴展:在上面這五種替換結構中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)) 

$ echo $((3>2)) 

$ echo $((25<3 ? 2:3)) 

$ echo $var

$ echo $((var=2+3)) 

$ echo $var 

$ echo $((var++)) 

$ echo $var 

$

好了,上面的例子足夠了,這也表明了這種擴展運算是很強大的。

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

$

上面是簡單的例舉四種模式匹配替換結構的用法。

  • 其他(見man bash中的Parameter Expansion)

${parameter/pattern/string}
              Pattern substitution.  The pattern is expanded to produce a pat‐
              tern  just  as in pathname expansion.  Parameter is expanded and
              the longest match of pattern against its value is replaced  with
              string.   If  pattern  begins with /, all matches of pattern are
              replaced  with  string.   Normally  only  the  first  match   is
              replaced.  If pattern begins with #, it must match at the begin‐
              ning of the expanded value of parameter.  If pattern begins with
              %,  it must match at the end of the expanded value of parameter.
              If string is null, matches of pattern are deleted and the / fol‐
              lowing pattern may be omitted.  If parameter is @ or *, the sub‐
              stitution operation is applied to each positional  parameter  in
              turn,  and the expansion is the resultant list.  If parameter is
              an array variable subscripted with  @  or  *,  the  substitution
              operation  is  applied  to each member of the array in turn, and
              the expansion is the resultant list.
shell中的括號(小括號,大括號/花括號)
 
  • 發表於 7年前 
  • 閱讀 15555 
  • 收藏 16 
  • 點贊 6 
  • 評論 0

  

在這裏我想說的是幾種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} 

$ echo $newvar ###變量newvar的值仍然是空,但上一命令行中${newvar:-a}被替換成了a

$ newvar=b 
$ echo ${newvar:-a} ###變量newvar的值不爲空時,此命令行中的${newvar:-b}被替換爲$newvar,即b 

$

對於${var:=string}的替換規則和${var:-string}是一樣的,所不同之處是${var:=string}若var爲空時,用string替換${var:=string}的同時,把string賦給變量var:


$ echo $newvar

$ echo ${newvar:=a} 

$ echo $newvar ###變量newvar被賦值爲a,同時${newvar:=a}被替換成a 

$ echo ${newvar:=b} ###變量newvar不爲空(其值已被賦爲a),則${newvar:=b}被替換爲newvar的值(即b) 

$ 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 

$ echo ${newvar:+b} 

$ echo $newvar 

$ 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的值} 

$

補充擴展:在上面這五種替換結構中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)) 

$ echo $((3>2)) 

$ echo $((25<3 ? 2:3)) 

$ echo $var

$ echo $((var=2+3)) 

$ echo $var 

$ echo $((var++)) 

$ echo $var 

$

好了,上面的例子足夠了,這也表明了這種擴展運算是很強大的。

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

$

上面是簡單的例舉四種模式匹配替換結構的用法。

  • 其他(見man bash中的Parameter Expansion)

${parameter/pattern/string}
              Pattern substitution.  The pattern is expanded to produce a pat‐
              tern  just  as in pathname expansion.  Parameter is expanded and
              the longest match of pattern against its value is replaced  with
              string.   If  pattern  begins with /, all matches of pattern are
              replaced  with  string.   Normally  only  the  first  match   is
              replaced.  If pattern begins with #, it must match at the begin‐
              ning of the expanded value of parameter.  If pattern begins with
              %,  it must match at the end of the expanded value of parameter.
              If string is null, matches of pattern are deleted and the / fol‐
              lowing pattern may be omitted.  If parameter is @ or *, the sub‐
              stitution operation is applied to each positional  parameter  in
              turn,  and the expansion is the resultant list.  If parameter is
              an array variable subscripted with  @  or  *,  the  substitution
              operation  is  applied  to each member of the array in turn, and
              the expansion is the resultant list.
發佈了85 篇原創文章 · 獲贊 126 · 訪問量 57萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章