[Linux] 使用 getopt 在 shell script 中解析命令列參數
最近學到在 Linux 上可以用 getopt 來輔助解析命令列參數 (command line parameters)~
getopt 是一個 command line 的 tool (跟 Linux 內建的 getopts 不一樣),
可以指定所謂的 short/long option 給 getopt,
getopt 會把符合的 short/long options 整理起來,並且把其他非 – 開頭的參數排在後面,
因此可以很方便的用它來分析 command line options~
舉例來說,下面的指令用 -o 指定了 -i, -o, -s 三種 short option,
其中 -i 和 -o 後面一定要帶一個參數 (單一 :),而 -s 後面則不需要帶參數~
–long 用來設定 long options,這邊分別定義了 –input, –output, –strip,
其中 –input 和 –output 後面一定要帶一個參數 (單一 :),而 –strip 後面則不需要帶參數~
testuser@localhost ~ getopt -o i:o:s --long input:,output:,strip -- aaa -i "input file" "bbb ccc" -o "output file" -s ddd -i 'input file' -o 'output file' -s -- 'aaa' 'bbb ccc' 'ddd'
可以看到 getopt 幫我們將命令列參數整理了一下,
有 – 開頭的 short/long option 排在前面,接著是一個 –,接著就是非 – 開頭的參數~
用在 shell script 裡時,可以用下面的程式來解析:
GETOPT_RESULT=$(getopt -o i:o:s --long input:,output:,strip -- "$@" 2>&1) || exit eval set -- "${GETOPT_RESULT}" # Read parsed command lines while true do case "$1" in -i|--input) INPUT_FILE="$2" shift 2 ;; -o|--output) OUTPUT_FILE="$2" shift 2 ;; -s|--strip) FLAG_STRIP=1 shift ;; --) # Currently we don't care about positional parameters shift break ;; *) # Should not go in here. break ;; esac done
如果給錯了 short/long option,getopt 也會藉由 stderr 來顯示錯誤~
例如用了 -x 選項時,因為我們並沒有將 -x 宣告為合法的選項 (用 -o 或 –long),
因此 getopt 會傳回錯誤,但 stdout 還是會將可以解析的部分吐出來:
testuser@localhost ~ getopt -o i:o:s --long input:,output:,strip -- aaa -x -i "input file" "bbb ccc" -o "output file" -s ddd getopt: invalid option -- 'x' -i 'input file' -o 'output file' -s -- 'aaa' 'bbb ccc' 'ddd'
另一點要注意的是,getopt 似乎舊版並不支援參數裡有空白字元,
因此後來有所謂的加強版 (現在一般的 Linux 上的應該都是)~
要確認是加強版的話,可以用 -T 選項,檢查 exit code == 4 就是新版的了:
testuser@localhost ~ getopt -T testuser@localhost ~ echo $? 4
參考資料:
Using getopts in bash shell script to get long and short command line options
Command Line Options: How To Parse In Bash Using “getopt”