12

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

4

4 回答 4

30

该命令基本上有两个版本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 -- "$@"`
else
    # Original getopt is available
    set -- `getopt ho:v "$@"`
fi

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

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

正确使用 GNU 增强的 getopt

让 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'

秘诀是"$@"在双引号非常重要的地方(第 1 行)和evalset命令(第 6 行)使用。

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

完整的工作示例

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 -- "$@"`
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 "$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 "$@"; 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下载

维基百科关于 getopts 条目的比较表比较了不同的特性。

于 2010-11-29T01:29:59.333 回答
15

使用getopts(带“s”)。

根据Bash FAQ 35

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

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

于 2010-04-28T10:30:31.863 回答
1

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

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

于 2011-10-07T11:50:52.827 回答
1

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

getopt vi: -v -i 100 file
于 2010-04-28T09:14:01.817 回答