我剛剛發現getopt
不是跨平臺的(特別是對於FreeBSD和Linux)。這個問題最好的解決方法是什麼?針對shell腳本的跨平臺getopt
回答
使用getopts
(帶有「s」)。
根據Bash FAQ 35:
除非它的版本從UTIL-Linux操作系統,並使用其先進的模式,從來沒有使用getopt的(1)。 getopt不能處理空的參數字符串或嵌入空白的參數。請忘記它曾經存在過。
POSIX shell(和其他)提供getopts,它可以安全地使用。
我使用Shell的助記符「S」,getopt「S」內置於BASH – 2012-12-19 05:53:12
@ Dennis Williamson請更新您的答案:根據(更新後)FAQ條目:**除非是util-linux的版本,否則使用其高級模式,絕不使用getopt(1)。 ... ** – Florian 2015-10-16 11:10:50
@Florian:更新。謝謝。 – 2015-10-16 17:55:26
getopt
的基本語法是跨平臺的。
getopt vi: -v -i 100 file
getopt
命令基本上有兩個版本:原始版本和GNU增強版本。 GNU增強版本與原始版本向後兼容,所以如果您只使用原始版本的功能,它將與兩者兼容。
檢測哪些可用的getopt的版本
可以檢測哪個版本可用,並使用增強的功能,如果GNU增強版本,並限制自己原有的特色,如果GNU增強版本無法使用。增強版有一個-T
選項用於測試哪個版本可用。
getopt -T > /dev/null
if [ $? -eq 4 ]; then
# GNU enhanced getopt is available
set -- `getopt --long help,output:,version --options ho:v -- "[email protected]"`
else
# Original getopt is available
set -- `getopt ho:v "[email protected]"`
fi
考慮使用內置的shell命令getopts
(以「S」)來代替,因爲它更便於攜帶。但是,getopts
不支持長選項(例如--help
)。
如果您喜歡長選項,請使用getopt
並使用上述測試來查看是否可以使用GNU增強版getopt
。如果增強版本不可用,則腳本可以優雅地降級爲使用原始版本getopt
(不支持長選項名稱和不支持空白)或使用getopts
(不支持長選項名稱)。
使用GNU getopt的增強正確
獲取GNU增強版本與空白正確處理參數是棘手的。下面是它是如何做的:
ARGS=`getopt --long help,output:,verbose --options ho:v -- "[email protected]"`
if [ $? -ne 0 ]; then
echo "Usage error (use -h for help)" >&2
exit 2
fi
eval set -- $ARGS
# Parameters are now sorted: options appear first, followed by --, then arguments
# e.g. entering: "foo bar" -o abc baz -v
# produces: -o 'abc' -v -- 'foo bar' 'baz'
祕訣是使用"[email protected]"
其中雙引號是非常重要的(在1號線),並eval
的設置命令(6號線)。
因此可以檢測並處理由getopt
引發的錯誤,getopt
的調用與eval
分開進行,其中兩個由ARGS變量鏈接。
完整工作示例
PROG=`basename $0`
getopt -T > /dev/null
if [ $? -eq 4 ]; then
# GNU enhanced getopt is available
ARGS=`getopt --name "$PROG" --long help,output:,verbose --options ho:v -- "[email protected]"`
else
# Original getopt is available (no long option names, no whitespace, no sorting)
ARGS=`getopt ho:v "[email protected]"`
fi
if [ $? -ne 0 ]; then
echo "$PROG: usage error (use -h for help)" >&2
exit 2
fi
eval set -- $ARGS
while [ $# -gt 0 ]; do
case "$1" in
-h | --help) HELP=yes;;
-o | --output) OUTFILE="$2"; shift;;
-v | --verbose) VERBOSE=yes;;
--) shift; break;; # end of options
esac
shift
done
if [ $# -gt 0 ]; then
# Remaining parameters can be processed
for ARG in "[email protected]"; do
echo "$PROG: argument: $ARG"
done
fi
echo "$PROG: verbose: $VERBOSE"
echo "$PROG: output: $OUTFILE"
echo "$PROG: help: $HELP"
這個例子可以從https://gist.github.com/hoylen/6607180
比較表上Wikipedia's entry on getopts比較了不同特徵下載。
是的,'getopts'(帶s)是另一種選擇。可移植性純粹主義者仍然更喜歡getopt,因爲在1986年以前,古代Bourne炮彈中沒有getopts,但是這是一個不好的理由,因爲大多數/所有現代炮彈都支持得到選擇。更好的原因是如果可用,則可以輕鬆利用GNU增強的getup。 GNU增強的getopt允許操作數與選項混合並支持長選項名稱(這兩個功能都是getopts不支持的 - 參見[比較表] [1])。 – Hoylen 2014-06-17 03:19:20
當我運行'eval set - $ ARGS'時,爲什麼會打印一個空的'--'?這是非常刺激。 – Hindol 2015-07-01 07:00:44
Bash的內置getopts的功能,可用於便攜分析短期和長期的選項,請參閱:
Using getopts in bash shell script to get long and short command line options
- 1. 跨平臺的shell腳本
- 2. 針對windows,Linux,MacOS的跨平臺腳本X
- 3. 跨平臺的Emacs腳本
- 4. 跨平臺shell腳本查找所有文件到maxdepth
- 5. 分發跨平臺的python3腳本
- 6. 跨平臺安裝腳本的語言
- 7. Ruby on rails跨平臺win/linux腳本
- 8. 跨平臺NPM啓動腳本
- 9. 針對平板電腦的跨平臺非瀏覽器開發?
- 10. 跨平臺版本的__PTRDIFF_TYPE__
- 11. 跨平臺替代windows shell擴展 - WebDAV平臺?
- 12. 針對多平臺的AVD
- 13. 僅針對用戶界面的C++跨平臺移動框架
- 14. 針對iOS的跨平臺設備消息傳遞?
- 15. 針對查詢字符串的跨平臺Url編碼
- 16. 針對Python跨平臺監聽器服務器的建議
- 17. 針對移動應用的跨平臺表單功能
- 18. 針對PaaS供應商的跨平臺API?
- 19. 針對諾基亞和Android的跨平臺移動開發
- 20. 針對移動解決方案的跨平臺ORM
- 21. 針對linux的g ++編譯只有跨平臺
- 22. 多平臺腳本
- 23. Getopt in shell
- 24. 跨平臺
- 25. Android跨平臺
- 26. SWIG跨平臺
- 27. 跨平臺Bonjour
- 28. 跨平臺C?
- 29. MD5跨平臺
- 30. 跨平臺CSRF
如果你開始使用的GNU getopt的長選項等,並打算讓你現有的代碼便攜和儘可能少的變化,那麼你可能會發現http://stackoverflow.com/a/37087374/324105有用。 – phils 2016-10-28 23:18:05