shell中的括號(小括號,中括號,大括號) linux中的(),(()),[],[[]],{}的作用


一、小括號,園括號()

  1、單小括號 ()

    ①命令組。括號中的命令將會新開一個子shell順序執行,所以括號中的變量不能夠被腳本余下的部分使用。括號中多個命令之間用分號隔開,最后一個命令可以沒有分號,各命令和括號之間不必有空格。
    ②命令替換。等同於`cmd`,shell掃描一遍命令行,發現了$(cmd)結構,便將$(cmd)中的cmd執行一次,得到其標准輸出,再將此輸出放到原來命令。有些shell不支持,如tcsh。
    ③用於初始化數組。如:array=(a b c d)
 
 

  2、雙小括號 ((  ))

    ①整數擴展。這種擴展計算是整數型的計算,不支持浮點型。((exp))結構擴展並計算一個算術表達式的值,如果表達式的結果為0,那么返回的退出狀態碼 為1,或者 是"假",而一個非零值的表達式所返回的退出狀態碼將為0,或者是"true"。若是邏輯判斷,表達式exp為真則為1,假則為0。
    ②只要括號中的運算符、表達式符合C語言運算規則,都可用在$((exp))中,甚至是三目運算符。作不同進位(如二進制、八進制、十六進制)運算時,輸出結果全都自動轉化成了十進制。如:echo $((16#5f)) 結果為95 (16進位轉十進制)
    ③單純用 (( )) 也可重定義變量值,比如 a=5; ((a++)) 可將 $a 重定義為6
    ④雙括號中的變量可以不使用$符號前綴。括號內支持多個表達式用逗號分開。
[python] view plain copy
  1. if ($i<5)  
  2. if [ $i -lt 5 ]  
  3. if [ $a -ne 1 -a $a != 2 ]  
  4. if [ $a -ne 1] && [ $a != 2 ]  
  5. if [[ $a != 1 && $a != 2 ]]  
  6.    
  7. for i in $(seq 4);do echo $i;done  
  8. for i in `seq 4`;do echo $i;done  
  9. for ((i=0;i<5;i++));do echo $i;done  
  10. for i in {0..4};do echo $i;done  

二)中括號,方括號[]

  1、單中括號 []

    ①bash 的內部命令,[和test是等同的。如果我們不用絕對路徑指明,通常我們用的都是bash自帶的命令。if/test結構中的左中括號是調用test的命 令標識,右中括號是關閉條件判斷的。這個命令把它的參數作為比較表達式或者作為文件測試,並且根據比較的結果來返回一個退出狀態碼。if/test結構中 並不是必須右中括號,但是新版的Bash中要求必須這樣。
    ②Test和[]中可用的比較運算符只有==和!=,兩者都是用於字符串比較的,不可用於整數比較,整數比較只能使用-eq,-gt這種形式。無論是字符 串比較還是整數比較都不支持大於號小於號。如果實在想用,對於字符串比較可以使用轉義形式,如果比較"ab"和"bc":[ ab \< bc ],結果為真,也就是返回狀態為0。[ ]中的邏輯與和邏輯或使用-a 和-o 表示。
    ③字符范圍。用作正則表達式的一部分,描述一個匹配的字符范圍。作為test用途的中括號內不能使用正則。
    ④在一個array 結構的上下文中,中括號用來引用數組中每個元素的編號。
 
 

  2、雙中括號[[ ]]

    ①[[是 bash 程序語言的關鍵字。並不是一個命令,[[ ]] 結構比[ ]結構更加通用。在[[和]]之間所有的字符都不會發生文件名擴展或者單詞分割,但是會發生參數擴展和命令替換。
    ②支持字符串的模式匹配,使用=~操作符時甚至支持shell的正則表達式。字符串比較時可以把右邊的作為一個模式,而不僅僅是一個字符串,比如[[ hello == hell? ]],結果為真。[[ ]] 中匹配字符串或通配符,不需要引號。
    ③使用[[ ... ]]條件判斷結構,而不是[ ... ],能夠防止腳本中的許多邏輯錯誤。比如,&&、||、<和> 操作符能夠正常存在於[[ ]]條件判斷結構中,但是如果出現在[ ]結構中的話,會報錯。
    ④bash把雙中括號中的表達式看作一個單獨的元素,並返回一個退出狀態碼。

三)大括號、花括號 {}

  1、常規用法。

    ①大括號拓展。(通配(globbing))將對大括號中的文件名做擴展。在大括號中,不允許有空白,除非這個空白被引用或轉義。第一種:對大括號中的以 逗號分割的文件列表進行拓展。如 touch {a,b}.txt 結果為a.txt b.txt。第二種:對大括號中以點點(..)分割的順序文件列表起拓展作用,如:touch {a..d}.txt 結果為a.txt b.txt c.txt d.txt
[python] view plain copy
  1. bogon:/home/bash # ls {ex1,ex2}.sh  
  2. ex1.sh  ex2.sh  
  3. bogon:/home/bash # ls {ex{1..3},ex4}.sh  
  4. ex1.sh  ex2.sh  ex3.sh  ex4.sh  
  5. bogon:/home/bash # ls {ex[1-3],ex4}.sh  
  6. ex1.sh  ex2.sh  ex3.sh  ex4.sh  
    ②代碼塊,又被稱為內部組,這個結構事實上創建了一個匿名函數 。與小括號中的命令不同,大括號內的命令不會新開一個子shell運行,即腳本余下部分仍 可使用括號內變量。括號內的命令間用分號隔開,最后一個也必須有分號。{}的第一個命令和左括號之間必須要有一個空格。
 
 

   2)幾種特殊的替換結構:${var:-string},${var:+string},${var:=string},${var:?string}

      A,${var:-string}和${var:=string}:若變量var為空,則用在命令行中用string來替換${var:- string},否則變量var不為空時,則用變量var的值來替換${var:-string};對於${var:=string}的替換規則 和${var:-string}是一樣的,所不同之處是${var:=string}若var為空時,用string替換${var:=string}的 同時,把string賦給變量var: ${var:=string}很常用的一種用法是,判斷某個變量是否賦值,沒有的話則給它賦上一個默認值。
      B. ${var:+string}的替換規則和上面的相反,即只有當var不是空的時候才替換成string,若var為空時則不替換或者說是替換成變量 var的值,即空值。(因為變量var此時為空,所以這兩種說法是等價的) 
      C,${var:?string}替換規則為:若變量var不為空,則用變量var的值來替換${var:?string};若變量var為空,則把string輸出到標准錯誤中,並從腳本中退出。我們可利用此特性來檢查是否設置了變量的值。
      補充擴展:在上面這五種替換結構中string不一定是常值的,可用另外一個變量的值或是一種命令的輸出。

  3)四種模式匹配替換結構${var%pattern},${var%%pattern},${var#pattern},${var##pattern}

     第一種模式:${variable%pattern},這種模式時,shell在variable中查找,看它是否一給的模式pattern結尾,如果是,就從命令行把variable中的內容去掉右邊最短的匹配模式
     第二種模式: ${variable%%pattern},這種模式時,shell在variable中查找,看它是否一給的模式pattern結尾,如果是,就從命令行把variable中的內容去掉右邊最長的匹配模式
     第三種模式:${variable#pattern} 這種模式時,shell在variable中查找,看它是否一給的模式pattern開始,如果是,就從命令行把variable中的內容去掉左邊最短的匹配模式
     第四種模式: ${variable##pattern} 這種模式時,shell在variable中查找,看它是否一給的模式pattern結尾,如果是,就從命令行把variable中的內容去掉右邊最長的匹配模式
     這四種模式中都不會改變variable的值,其中,只有在pattern中使用了*匹配符號時,%和%%,#和##才有區別。結構中的pattern 支持通配符,*表示零個或多個任意字符,?表示零個或一個任意字符,[...]表示匹配中括號里面的字符,[!...]表示不匹配中括號里面的字符
[python] view plain copy
  1. bogon:/home/bash # var=testcase  
  2. bogon:/home/bash # echo $var  
  3. testcase  
  4. bogon:/home/bash # echo ${var%s*e}  
  5. testca  
  6. bogon:/home/bash # echo $var  
  7. testcase  
  8. bogon:/home/bash # echo ${var%%s*e}  
  9. te  
  10. bogon:/home/bash # echo ${var#?e}  
  11. stcase  
  12. bogon:/home/bash # echo ${var##?e}  
  13. stcase  
  14. bogon:/home/bash # echo ${var##*e}  
  15.   
  16. bogon:/home/bash # echo ${var##*s}  
  17. e  
  18. bogon:/home/bash # echo ${var##test}  
  19. case 

 

 

()

命令組.在括號中的命令列表, 將會作為一個子shell來運行.
在括號中的變量,由於是在子shell中,所以對於腳本剩下的部分是不可用的. 父進程, 也就是腳本本身, 將不能夠讀取在子進程中創建的變量, 也就是在子shell中創建的變量.
(cmd1;cmd2;cmd3)

初始化數組.
Array=(element1 element2 element3)

$(...)

相當於`...`命令,返回括號中命令執行的結果

let命令


(( ))
  
(( ... ))結構可以用來計算並測試算術表達式的結果. 退出狀態將會與[ ... ]結構完全相反!還可應用到c風格的for,while循環語句,(( )) 中,所有的變量(加不加$無所謂)都是數值。

$((...))結構的表達式是C風格的表達式,其返回的結果是表達式值,其中變量引用可不用‘$’(當然也可以)

for((...;...;...))
do
  cmd
done

while ((...))
do
  cmd
done

比較操作符

<

    小於

    (("$a" < "$b"))
<=

    小於等於

    (("$a" <= "$b"))
>

    大於

    (("$a" > "$b"))
>=

    大於等於

    (("$a" >= "$b"))


(( 0 ))
echo "Exit status of \"(( 0 ))\" is $?."         # 1
   
(( 1 ))
echo "Exit status of \"(( 1 ))\" is $?."         # 0

(( 5 > 4 ))                                      # 真
echo "Exit status of \"(( 5 > 4 ))\" is $?."     # 0

(( 5 > 9 ))                                      # 假
echo "Exit status of \"(( 5 > 9 ))\" is $?."     # 1

(( 5 - 5 ))                                      # 0
echo "Exit status of \"(( 5 - 5 ))\" is $?."     # 1

(( 5 / 4 ))                                      # 除法也可以.
echo "Exit status of \"(( 5 / 4 ))\" is $?."     # 0

(( 1 / 2 ))                                      # 除法的計算結果 < 1.
echo "Exit status of \"(( 1 / 2 ))\" is $?."     # 截取之后的結果為 0.
                                                  # 1

(( 1 / 0 )) 2>/dev/null                          # 除數為0, 非法計算.
#         
echo "Exit status of \"(( 1 / 0 ))\" is $?."     # 1


for ((a=1; a <= LIMIT ; a++))  # 雙圓括號, 並且"LIMIT"變量前面沒有"$".
do
   echo -n "$a "
done

while (( a <= LIMIT ))   # 雙圓括號, 變量前邊沒有"$".
do
   echo -n "$a "
   ((a += 1))   # let "a+=1"
done

a=2
b=$(($a*4))     #a=2 b=8
c=$((a*3))      #a=2 c=6


[ ]

條件測試表達式放在[ ]中. 值得注意的是[是shell內建test命令的一部分, 並不是/usr/bin/test中的外部命令的一個鏈接.

文件測試操作符(如果下面的條件成立將會返回真)

-e

    文件存在(推薦用)
-a

    文件存在(不推薦用)

-f

    表示這個文件是一個一般文件(並不是目錄或者設備文件)
-s

    文件大小不為零
-d

    表示這是一個目錄
-b

    表示這是一個塊設備(軟盤, 光驅, 等等.)
-c

    表示這是一個字符設備(鍵盤, modem, 聲卡, 等等.)
-p

    這個文件是一個管道
-h

    這是一個符號鏈接
-L

    這是一個符號鏈接
-S

    表示這是一個socket
-t

    文件(描述符)被關聯到一個終端設備上

    這個測試選項一般被用來檢測腳本中的stdin([ -t 0 ]) 或者stdout([ -t 1 ])是否來自於一個終端.
-r

    文件是否具有可讀權限(指的是正在運行這個測試命令的用戶是否具有讀權限)
-w

    文件是否具有可寫權限(指的是正在運行這個測試命令的用戶是否具有寫權限)
-x

    文件是否具有可執行權限(指的是正在運行這個測試命令的用戶是否具有可執行權限)
-g

    set-group-id(sgid)標記被設置到文件或目錄上

    如果目錄具有sgid標記的話, 那么在這個目錄下所創建的文件將屬於擁有這個目錄的用戶組, 而不必是創建這個文件的用戶組. 這個特性對於在一個工作組中共享目錄非常有用.

-u

    set-user-id (suid)標記被設置到文件上

    如果一個root用戶所擁有的二進制可執行文件設置了set-user-id標記位的話, 那么普通用戶也會以root權限來運行這個文件. [1] 這對於需要訪問系統硬件的執行程序(比如pppd和cdrecord)非常有用. 如果沒有suid標志的話, 這些二進制執行程序是不能夠被非root用戶調用的.

                  -rwsr-xr-t    1 root       178236 Oct  2  2000 /usr/sbin/pppd
                 

    對於設置了suid標志的文件, 在它的權限列中將會以s表示.
-k

    設置粘貼位

    對於"粘貼位"的一般了解, save-text-mode標志是一個文件權限的特殊類型. 如果文件設置了這個標志, 那么這個文件將會被保存到緩存中, 這樣可以提高訪問速度. [2] 粘貼位如果設置在目錄中, 那么它將限制寫權限. 對於設置了粘貼位的文件或目錄, 在它們的權限標記列中將會顯示t.

                  drwxrwxrwt    7 root         1024 May 19 21:26 tmp/
                 
    如果用戶並不擁有這個設置了粘貼位的目錄, 但是他在這個目錄下具有寫權限, 那么這個用戶只能在這個目錄下刪除自己所擁有的文件. 這將有效的防止用戶在一個公共目錄中不慎覆蓋或者刪除別人的文件. 比如說/tmp目錄. (當然, 目錄的所有者或者root用戶可以隨意刪除或重命名其中的文件.)

-O

    判斷你是否是文件的擁有者
-G

    文件的group-id是否與你的相同
-N

    從文件上一次被讀取到現在為止, 文件是否被修改過

f1 -nt f2

    文件f1比文件f2新
f1 -ot f2

    文件f1比文件f2舊
f1 -ef f2

    文件f1和文件f2是相同文件的硬鏈接
!

    "非" -- 反轉上邊所有測試的結果(如果沒給出條件, 那么返回真).


比較操作符


整數比較

-eq

    等於

-ne

    不等於

-gt

    大於

-ge

    大於等於

-lt

    小於

-le

    小於等於


字符串比較

=

    等於

==

    等於,與=等價.(==比較操作符在雙中括號對和單中括號對中的行為是不同的)

      [[ $a == z* ]]    # 如果$a以"z"開頭(模式匹配)那么結果將為真
      [[ $a == "z*" ]]  # 如果$a與z*相等(就是字面意思完全一樣), 那么結果為真.
      
      [ $a == z* ]      # 文件擴展匹配(file globbing)和單詞分割有效.
      [ "$a" == "z*" ]  # 如果$a與z*相等(就是字面意思完全一樣), 那么結果為真.

!=

    不等號(這個操作符將在[[ ... ]]結構中使用模式匹配)

<

    小於, 按照ASCII字符進行排序(注意"<"使用在[ ]結構中的時候需要被轉義)
>

    大於, 按照ASCII字符進行排序(注意">"使用在[ ]結構中的時候需要被轉義)

-z

    字符串為"null", 意思就是字符串長度為零
-n

    字符串不為"null".

-a

    邏輯與

-o

    邏輯或


{xxx,yyy,zzz,...}

大括號擴展.
echo {1..20}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
cat {file1,file2,file3} > combined_file
# 把file1, file2, file3連接在一起, 並且重定向到combined_file中.
cp file22.{txt,backup}
# 拷貝"file22.txt"到"file22.backup"中

在大括號中, 不允許有空白, 除非這個空白被引用或轉義.

echo {file1,file2}\ :{\ A," B",' C'}

file1 : A file1 : B file1 : C file2 : A file2 : B file2 : C

代碼塊


這個結構事實上創建了一個匿名函數(一個沒有名字的函數). 然而, 與"標准"函數不同的是, 在其中聲明的變量,對於腳本其他部分的代碼來說還是可見的(除了用declare,typeset命令聲明的變量)


()會開啟一個新的子shell,{}不會開啟一個新的子shell

(())常用於算術運算比較,[[]]常用於字符串的比較.

$()返回括號中命令執行的結果

$(())返回的結果是括號中表達式值

${ }參數替換與擴展

參數替換

${var}
${var}=$var

${var:-default}    ${var-default}
如果var未set,那么就是用default.兩者之間不同只有當var為空變量時,前者為default,后者為空.

${var:=default}    ${var=default}
如果var未set,那么就設置default.兩者之間不同只有當var為空變量時,前者設置為default,后者設置為空.

${var:+default}    ${var+default}
如果var被set,就是用default.未set,就使用null字符串.兩者之間不同只有當var為空變量時,前者為null字符串,后者為default.

上面三種參數替換中,第二種使用后變量的值被改變.

參數替換擴展

${#var}    ${#array}
字符串長度或數組第一個元素的字符串長度
例外:
${#*}、${#@}指位置參數的個數.
${#array},$[#array[@]}指數組元素的個數

${var#pattern}    ${var##pattern}
從var開頭刪除最近或最遠匹配pattern的子串.

${var%pattern}    ${var%%pattern}
從var結尾刪除最近或最遠匹配pattern的子串.

${var:pos}
變量var從位置pos開始擴展.

${var:pos:len}
從位置pos開始,並擴展len長度個字符

${var/pattern/replacement}    ${var//pattern/replacement}
使用replacement來替換var中的第一個或所有pattern的匹配.

${var/#pattern/replacement}
如果var的前綴匹配到了pattern,那么就用replacement來替換pattern.

${var/%pattern/replacement}
如果var的后綴匹配到了pattern,那么就用replacement來替換pattern.

${!varprefix*}    ${!varprefix@}
前邊所有聲明過的,以varprefix為前綴的變量名.


[[]]就是條件表達式,在bash中,字符串比較用  > < != == <= >= 只是在[]中 < >需要轉義;對於數值比較.用 -lt -le -eq -ge -gt 來比較,與[[]]中表達不太一樣,在[ ] 中的 < > 需要用轉義 \< \>,如果有多個表達式,在[[ ]] 中用 && || 來組合,而[] 中是用 -a -o 來組合

 

1.() 符號

  a.()會開啟一個新的子shell,{}不會開啟一個新的子shell

  b.在括號中的變量,由於是在子shell中,所以對於腳本剩下的部分是不可用的. 父進程, 也就是腳本本身, 將不能夠讀取在子進程中創建的變量, 也就是在子shell中創建的變量.

  c.$(...) 執行括號的內容,並返回結果,相當於`...`命令
  d.(())常用於算術運算比較,[[]]常用於字符串的比較.

2.[ ]符號

  a.條件測試表達式放在[ ]中. 值得注意的是[是shell內建test命令的一部分, 並不是/usr/bin/test中的外部命令的一個鏈接.

  b.文件存在 -e ,-a

  c.表示這個文件是一個一般文件 -f

  d.文件大小不為零 -s

  e.表示這是一個目錄 -d

  f.表示這是一個塊設備(軟盤, 光驅, 等等.) -b

  g.表示這是一個字符設備(鍵盤, modem, 聲卡, 等等.) -c

  h.這個文件是一個管道 -p
  i.這是一個符號鏈接 -h
  j.這是一個符號鏈接-L   

  k.-S 表示這是一個socket
  l.-t 文件(描述符)被關聯到一個終端設備上,這個測試選項一般被用來檢測腳本中的stdin([ -t 0 ]) 或者stdout([ -t 1 ])是否來自於一個終端.
  m.-r 文件是否具有可讀權限(指的是正在運行這個測試命令的用戶是否具有讀權限)
  n.-w 文件是否具有可寫權限(指的是正在運行這個測試命令的用戶是否具有寫權限)
  o. -x 文件是否具有可執行權限(指的是正在運行這個測試命令的用戶是否具有可執行權限)


3.{}符號    

  ${ }參數替換與擴展


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM