Bash

getopt、getopts 或手動解析 - 當我想同時支持短選項和長選項時使用什麼?

  • April 13, 2020

目前我正在編寫一個具有以下要求的 Bash 腳本:

  • 它應該在各種各樣的 Unix/Linux 平台上執行
  • 它應該支持短選項和(GNU)長選項

我知道這getopts將是可移植性方面的首選方式,但 AFAIK 它不支持長選項。

getopt支持長選項,但BashGuide強烈反對它:

永遠不要使用 getopt(1)。getopt 無法處理空參數字元串或帶有嵌入空格的參數。請忘記它曾經存在過。

因此,仍然有手動解析的選項。這很容易出錯,產生了相當多的樣板程式碼,我需要自己處理錯誤(我想自己getopt(s)做錯誤處理)。

那麼,在這種情況下,什麼是首選呢?

如果它必須可移植到一系列 Unices,則必須堅持使用 POSIX sh。AFAIU 那裡你別無選擇,只能手動滾動參數處理。

getoptvsgetopts似乎是一個宗教問題。至於Bash FAQgetopt中反對的論點:

  • getopt無法處理空參數字元串”似乎指的是可選參數的已知問題,它看起來getopts根本不支持(至少從help getoptsBash 4.2.24 的閱讀中)。來自man getopt

getopt(3) 可以解析帶有可選參數的長選項,這些可選參數被賦予一個空的可選參數(但不能對短選項執行此操作)。此 getopt(1) 將空的可選參數視為不存在。

我不知道 “getopt不能處理的地方

$$ … $$帶有嵌入空格的參數”來自,但讓我們測試一下:

  • test.sh:
#!/usr/bin/env bash
set -o errexit -o noclobber -o nounset -o pipefail
params="$(getopt -o ab:c -l alpha,bravo:,charlie --name "$0" -- "$@")"
eval set -- "$params"

while true
do
   case "$1" in
       -a|--alpha)
           echo alpha
           shift
           ;;
       -b|--bravo)
           echo "bravo=$2"
           shift 2
           ;;
       -c|--charlie)
           echo charlie
           shift
           ;;
       --)
           shift
           break
           ;;
       *)
           echo "Not implemented: $1" >&2
           exit 1
           ;;
   esac
done
  • 跑:
$ ./test.sh -
$ ./test.sh -acb '   whitespace   FTW   '
alpha
charlie
bravo=   whitespace   FTW   
$ ./test.sh -ab '' -c
alpha
bravo=
charlie
$ ./test.sh --alpha --bravo '   whitespace   FTW   ' --charlie
alpha
bravo=   whitespace   FTW   
charlie

對我來說看起來像是檢查和配對,但我相信有人會展示我是如何完全誤解了這句話的。當然,便攜性問題仍然存在;您必須決定在具有較舊或沒有可用 Bash 的平台上投入多少時間。我自己的建議是使用YAGNIKISS指南——只為那些你知道將要使用的特定平台開發。隨著開發時間的延長,Shell 程式碼的可移植性通常會達到 100%。

引用自:https://unix.stackexchange.com/questions/62950