bash 用于 shell 脚本的跨平台 getopt

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2721946/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 22:01:12  来源:igfitidea点击:

Cross-platform getopt for a shell script

bashshellcross-platformgetopt

提问by codeholic

I've just found out that getoptis not cross-platform (in particular for FreeBSD and Linux). What is the best workaround for this issue?

我刚刚发现它getopt不是跨平台的(特别是对于 FreeBSD 和 Linux)。此问题的最佳解决方法是什么?

回答by Hoylen

There are essentially two versions of the getoptcommand: the original version and the GNU enhanced version. The GNU enhanced version is backward compatible with the original version, so if you only use the features of the original version it will work with both.

getopt命令基本上有两个版本:原始版本和 GNU 增强版本。GNU 增强版与原始版本向后兼容,因此如果您只使用原始版本的功能,它将同时适用于两者。

Detect which version of getopt is available

检测可用的 getopt 版本

You can detect which version is available and use the enhanced features if the GNU enhanced version is available, and limit yourself to the original features if the GNU enhanced version is not available. The enhanced version has a -Toption for testing which version is available.

如果有 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 -- "$@"`
else
    # Original getopt is available
    set -- `getopt ho:v "$@"`
fi

Consider using built-in shell command getopts(with an "s") instead, because it is more portable. However, getoptsdoes not support long options (e.g. --help).

考虑使用内置的 shell 命令getopts(带有“s”),因为它更便于移植。但是,getopts不支持长选项(例如--help)。

If you like long options, use getoptand use the above test to see if the GNU enhanced version of getoptis available or not. If the enhanced version is not available, the script can gracefully degrade to either using the original version of getopt(with no support for long option names and no whitespace support) or using getopts(with no support for long option names).

如果您喜欢长选项,请使用getopt并使用上面的测试来查看 GNU 增强版本getopt是否可用。如果增强版本不可用,脚本可以优雅地降级为使用原始版本getopt(不支持长选项名称和空格支持)或使用getopts(不支持长选项名称)。

Using GNU enhanced getopt properly

正确使用 GNU 增强的 getopt

Getting the GNU enhanced version to process arguments with whitespace properly is tricky. Here's how it is done:

让 GNU 增强版本正确处理带有空格的参数是很棘手的。这是如何完成的:

ARGS=`getopt --long help,output:,verbose --options ho:v -- "$@"`
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'

The secret is to use "$@"where the double quotes are very important (in line 1), and to evalthe setcommand (in line 6).

秘诀就是使用"$@"其中双引号是非常重要的(在1号线),并eval设定的命令(6号线)。

So errors raised by getoptcan be detected and handled, the call to getoptis done separately from the evalwith the two linked by the ARGS variable.

因此getopt可以检测和处理由 引发的错误,对 的调用与由 ARGS 变量链接的两者getopt分开完成eval

Complete working example

完整的工作示例

PROG=`basename 
getopt vi: -v -i 100 file
` getopt -T > /dev/null if [ $? -eq 4 ]; then # GNU enhanced getopt is available ARGS=`getopt --name "$PROG" --long help,output:,verbose --options ho:v -- "$@"` else # Original getopt is available (no long option names, no whitespace, no sorting) ARGS=`getopt ho:v "$@"` 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 "" in -h | --help) HELP=yes;; -o | --output) OUTFILE=""; 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 "$@"; do echo "$PROG: argument: $ARG" done fi echo "$PROG: verbose: $VERBOSE" echo "$PROG: output: $OUTFILE" echo "$PROG: help: $HELP"

This example can be downloaded from https://gist.github.com/hoylen/6607180

这个例子可以从https://gist.github.com/hoylen/6607180下载

The comparison table on Wikipedia's entry on getoptscompares the different features.

维基百科上 getopts 条目的比较表比较了不同的功能。

回答by Paused until further notice.

Use getopts(with an "s").

使用getopts(带“s”)。

According to Bash FAQ 35:

根据Bash 常见问题 35

Unless it's the version from util-linux, and you use its advanced mode, never use getopt(1). getopt cannot handle empty arguments strings, or arguments with embedded whitespace. Please forget that it ever existed.

The POSIX shell (and others) offer getopts which is safe to use instead.

除非它是来自 util-linux 的版本,并且您使用它的高级模式,否则永远不要使用 getopt(1)。getopt 无法处理空参数字符串或带有嵌入空格的参数。请忘记它曾经存在过。

POSIX shell(和其他 shell)提供了可以安全使用的 getopts。

回答by codeholic

Basic syntax for getoptis cross-platform.

的基本语法getopt是跨平台的。

##代码##

回答by Arvid Requate

The Bash builtin getopts function can be used to parse short and long options portably, see:

Bash 内置 getopts 函数可用于可移植地解析短选项和长选项,请参阅:

Using getopts in bash shell script to get long and short command line options

在 bash shell 脚本中使用 getopts 获取长短命令行选项