Linux Shell程式設計(5)——shell特殊字元(下)

尹成發表於2014-09-30
{}


程式碼塊[花括號]. 這個結構也是一組命令程式碼塊,事實上,它是匿名的函式。然而與一個函式所不同的,在程式碼塊裡的變數仍然能被指令碼後面的程式碼訪問。


 bash$ { local a;
     a=123; }
 bash: local: can only be used in a
function
       


a=123
{ a=321; }
echo "a = $a"   # a = 321   (結果是在程式碼塊裡的值)




由花括號括起的程式碼塊可以引起輸入輸出的I/O重定向。


#!/bin/bash
# 從/etc/fstab檔案裡按一次一行地讀.


File=/etc/fstab


{
read line1
read line2
} < $File


echo "First line in $File is:"
echo "$line1"
echo
echo "Second line in $File is:"
echo "$line2"


exit 0


# 現在,你如何解析每一行的分割符?
# 提示: 使用awk.


  把一個程式碼塊的結果寫進一個檔案


#!/bin/bash
# rpm-check.sh


# 查詢一個rpm安裝包的描述,軟體清單,和是否它能夠被安裝.
# 並把結果儲存到一個檔案中.

# 這個指令碼使用一個程式碼塊來舉例說明。


SUCCESS=0
E_NOARGS=65


if [ -z "$1" ]
then
  echo "Usage: `basename $0` rpm-file"
  exit $E_NOARGS
fi  



  echo
  echo "Archive Description:"
  rpm -qpi $1       # 查詢軟體包的描述.
  echo
  echo "Archive Listing:"
  rpm -qpl $1       # 查詢軟體包中的軟體清單.
  echo
  rpm -i --test $1  # 查詢該軟體包能否被安裝.
  if [ "$?" -eq $SUCCESS ]
  then
    echo "$1 can be installed."
  else
    echo "$1 cannot be installed."
  fi  
  echo
} > "$1.test"       # 把程式碼塊的所有輸出重定向到一個檔案中。


echo "Results of rpm test in file $1.test"


# 參考rpm的man手冊來理解上面所用的選項。


exit 0

不像一個用圓括號括起來的命令組,一個用花括號括起的程式碼塊不會以一個子shell執行。[2]


{} \;
路徑名. 基本上用於find命令裡.它不是shell內建的.



分號";"結束find命令中-exec選項的命令序列.它應該轉義一下以免被shell誤解釋。


[ ]
測試.


測試在[ ]中的表示式. 注意[是shell內建的測試的一部分(同義於測試),並非 是外部命令/usr/bin/test的連結.


[[ ]]
測試.


測試[[ ]]之中的表示式(shell的關鍵字).


參考[[ ... ]]結構的討論.


[ ]
陣列元素.


在陣列的上下文中,方括號表示陣列的每個元素的數字編號.
   1 Array[1]=slot_1
   2 echo ${Array[1]}


[ ]
字符集的範圍.


用於正規表示式的一部分,方括號描述一個匹配的字符集範圍.


(( ))
整數擴充套件.


擴充套件並計算(( ))裡的整數表示式[譯者注:粗心的讀者要注意了,是整數計算,可不能用來做浮點計算].


參考(( ... ))結構的討論.


> &> >& >> <
redirection重定向.


scriptname >filename重定向scriptname的輸出到檔案filename中去. 如果檔案filename存在則將會被覆蓋.


command &>filename 會重定向命令command標準輸出(stdout)和標準錯誤(stderr)到檔案filename中.


command >&2 把命令command的標準輸出(stdout)重定向到標準錯誤(stderr).


scriptname >>filename appends把指令碼scriptname的輸出追加到檔案filename.如果filename不存在,則它會被建立.


程式替換.


(command)>


<(command)


在不同的上下文中, 字元 "<"和">"會被當作字元比較操作符.


在另一種不同的上下文中, 字元"<"和">"被當作整數比較操作符. 請參考例子 12-9.


<<
在here document中使用的重定向.


<<<
在 here string中使用的重定向.


<, >
ASCII比較.
veg1=carrots
veg2=tomatoes


if [[ "$veg1" < "$veg2" ]]
then
  echo "Although $veg1 precede $veg2 in the dictionary,"
  echo "this implies nothing about my culinary preferences."
else
  echo "What kind of dictionary are you using, anyhow?"
fi


\<, \>
在 regular expression中的單詞界線.


bash$ grep '\<the\>' textfile


|


管道. 把上一個命令的輸出傳給下一個命令,或是shell. 這是連線命令的一種方法.


echo ls -l | sh
#  把"echo ls -l"的輸出傳給shell,
#+ 這等同與直接的"ls -l".




cat *.lst | sort | uniq
# 合併且排序所有的".lst"檔案,然後刪除多餘的相同行.


經典的程式間通訊方法之一的管道能把一個程式的標準輸出發到另一個程式的標準輸入.在一種典型的情況,一個命令,比如說cat或echo, 管道傳遞一個資料流給過濾器(一個改變了它的輸入的命令)。


cat $filename1 $filename2 | grep $search_word


一個命令或一組命令的輸出可以由管道傳給一個指令碼.
#!/bin/bash
# uppercase.sh : 把輸入字元改為大寫.


tr 'a-z' 'A-Z'
#  字母的範圍一定要引號引起來,
#+ 這樣才能保護檔名而不會被擴充套件成單個字母的檔名.


exit 0
現在,讓我們把ls -l的輸出用管道與這個指令碼連起來.
 bash$ ls -l | ./uppercase.sh
 -RW-RW-R--    1 BOZO  BOZO       109 APR  7 19:49 1.TXT
 -RW-RW-R--    1 BOZO  BOZO       109 APR 14 16:48 2.TXT
 -RW-R--R--    1 BOZO  BOZO       725 APR 20 20:56 DATA-FILE

管道里的每一個程式的標準輸出都被當成下一個命令的標準輸入. 如果不是這種情況,那麼資料流會阻塞,並且管道不會引起預期的效果。
cat file1 file2 | ls -l | sort
# 來自"cat file1 file2"的輸出會消失.


管道以子程式來執行, 因此不能引起變數的改變。
variable="initial_value"
echo "new_value" | read variable
echo "variable = $variable"     # variable = initial_value


如果在管道中的一個命令失敗了,會過早的終結整個管道的執行。這稱為管道破壞(broken pipe),這時會傳送一個叫SIGPIPE 的訊號.


>|
強迫重定向 (即使noclobber選項設定). 這會強迫覆蓋一個存在的檔案.


||
或邏輯操作符. 在一個測試結構中,||操作符當測試條件的任何一個為真時返回0 (成功)的標誌.


&
在後臺執行作業. 一個後面跟一個&的命令會在後臺執行.

相關文章