Skip to content

Classic Shell Scripting 讀書筆記 (三)

  • Ops

test 命令

  • POSIX 將 test 的參數描述為「表達式」:
    • 一元(unary)表達式:由看似一個選項(如-d)與相對應的運算數組成(基本上是一個文件名)
    • 二元(binary)表達式:兩個運算數與一個內嵌的運算元組成,做某種比較操作
  • test 命令有另一種形式 [ expression ],方括號與表達式一定要以空白隔開

  • 表達式可以前置 ! 表示否定

在 XSI 兼容的系統裡,-a 意義等同於 &&; 為了可移植性,建議使用多重條件而非 -a, -o

使用 test 的訣竅

  • 須有參數(避免 null),因此變量展開都要以引號括起來
  • 為了可移植最大化,可以替比較字符串加上前綴 X,例如 if [ "X$answer" = "Xyes" ],可以避免字符串為空或開頭帶減號而混淆 test 命令
  • test 是可以被愚弄的,例如 test -r a_file && cat_file,a_file 可能會在執行 test 與執行 cat 之間改變
  • 只能做整數測試

範例:檢查輸入參數

case 語句

  • 比 if/else 更適合用來進行模式匹配
  • 圓右括號是 Shell 語法裡唯一的不對稱定界符
  • 默認模式(*)結尾的 ;; 可加可不加

for 語句

for 循環裡的 in 列表是可選的,如果省略,則會遍歷命令行參數

while 與 until 語句

  • while, until 差別僅在於如何透過 condition 來退出
  • break, continue 特別具備中斷或繼續多個循環層級的能力,彌補 Shell 語言裡 goto 關鍵字的不足
  • break, continue 可接受參數指出要中斷或繼續多少個被包含的循環

以 shift 處理選項

執行 shift 後,$1 會消失並以 $2 取代,以此類推往後遞進

範例: 選項處理的流程控制

  • 傳統上,以 -- 結束選項

getopts

  • 用來簡化選項處理
  • 用一個字串表示合法選項,如果選項字母後面跟著冒號(:),代表需要一個參數
  • 一旦遇到帶參數的選項,getops 會將參數值設置到變量 OPTARG
  • 變量 OPTIND 代表下一個要處理的參數的索引值

與上方範例比較:

  1. 不須開頭的減號
  2. 自動處理 -- 的情況
  3. 自動顯示非法選項的錯誤訊息

將冒號置於選項字串作為第一個字元,可以改變 getopts 的行為:不顯示任何錯誤訊息,不合法的選項可在 '?' 情況裡自行處理

函數

  • 必須事先定義,可置於腳本起始處,或放在另一個文件以點號(.)命令取用
  • 函數中的參數獨立於父腳本,函數執行時,父腳本參數會臨時被覆蓋(shadowed)或隱藏
  • 使用exit 會終止整個腳本;使用 return 則返回一個退出值父腳本,將函數設計成返回{0,1}可取代 test
  • 若未在 return 提供參數,則預設為最後一個執行命令的退出碼,嚴謹的寫法為 return $?
  • POSIX Shell 的函數沒有提供局部變量,所有函數都與父腳本共享變量

標準輸入、輸出、錯誤輸出

  • 程序應有一個數據來源、數據出口以及報告問題的地方
  • 程序不知道也不在意輸入輸出背後是哪些設備,可以預期的是,在程序啟動時,這些標準位置都已經準備好被使用了
  • 這樣的程序可以被稱為 filter,因為它們過濾了數據流

read

將訊息讀入成一個或多個 shell 變量

任何命令都能將輸出透過管道傳送給 read,在循環的情況下特別有用

範例: 逐行
讀取 /etc/passwd

也可以寫成這樣

範例:查找、取代並建立多個目錄

文件描述符

  • UNIX 以一個小的整數表示每個進程的打開文件,成為文字描述符(file descriptors)

  • 傳統上,Shell 允許處理最多 10 個打開文件,描述符從 0 至 9

  • 描述符 0、1、2 各自對應標準輸入、輸出、錯誤輸出

  • 1> 裡的 1 其實沒有必要,供輸出重定向的默認文件描述符是標準輸出

  • 2>&1 中的 &1 語法代表「無論描述符1在哪裡」,意思是將標準錯誤輸出定向至標準輸出,這四個字符必須連在一起不能有空格,另外須注意使用的順序

  • exec 命令能改變 Shell 本身的 I/O

  • 暫存文件描述符,以便在變更後回復

exec 命令

  • 除了上述改變 I/O 設置的用法,另一個用法是在當前進程中啟動新程序

  • 為單向操作,也就是說控制權不可能回到原腳本,唯一的例外是新程序無法被正常調用

printf 命令

  • 默認情況下,轉義序列如 \n\r 只在格式字串被解釋,對參數字串不解釋,除非使用 %b 格式
  • 可用來指定輸出字段的寬度、精度與對齊操作,格式為 %{flags}{width}.{precision}{format-specifier},可透過變量值動態指定

範例:對齊操作

範例:精度操作

範例:總是帶上正負號

範例:自動補0

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *