如何在Bash中生成getopts无法接受的参数列表



假设我在带有选项字符串":a:b"的Bash脚本中运行getopts,并提供以下命令行参数:

./script.sh -a foo bar -b bar zappo

"foo"的实例是选项a的预期参数,而选项b没有预期参数。但是,对于getopts来说,"bar"one_answers"zappo"这两个实例都是不可接受的。运行getopts之后,如何回显包含所有不可接受参数列表的变量?我如何制作"酒吧zappo"列表?谢谢

这里有一些代码,方便您:

#!/bin.bash
option_string=":a:b"
unexpected_parameters=""
OPTIND=1
while getopts "${option_string}" options; do
case ${options} in
a)
echo "-a triggered with parameter ${OPTARG}" >&2 # output to STDERR
;;
b)
echo "-b triggered" >&2 # output to STDERR
;;
?)
echo "invalid option: -${OPTARG}" >&2 # output to STDERR
;;
esac
#<insert code magic... unexpected_parameters="${unexpected_parameters} "$(MAGIC)"">
done
echo "unexpected parameters: ${unexpected_parameters}"

getopts在第一个非选项参数处停止处理。这是Posix风格的参数处理。在Posix风格的参数处理中,给定命令

utility -a foo bar -b bar zappo

utility不会将-b解释为命令行标志。如果-a取一个自变量,则bar将是第一个位置自变量,然后将有另外三个位置自变量-bbarzappo

GNU通过排列命令行参数来扩展此语法,从而使标志选项可以位于命令行中的任何位置。但是,如果您设置了环境变量POSIXLY_CORRECT,那么GNU实用程序(大部分)的行为将类似于普通的Posix实用程序。Posix C库函数getopt(3)(和getopt_long(3))的GNU版本默认使用GNU语法,并对POSIXLY_CORRECT环境变量做出适当反应。

然而,bashgetopts内建是严格的Posix风格。因此,在您的情况下,对于参数为foo的标志a,使用getopts ":a:b",您的循环将只执行一次。当getopts终止时,OPTIND被设置为第一个未使用的命令行参数的索引,在本例中为3(bar)。

如果你想使用带有GNU风格选项处理的getopts,你必须自己进行排列。例如,你可以这样做:

# Positional arguments are not necessarily unexpected; in fact, they are usually
# expected. So I accumulate them here in a bash array
positional=()
while (($#)); do
# If you really wanted to do GNU style processing, you'd need to special case
# '--' and "long options" starting with '--'. Here, I just do the simplest
# thing, which is to pass anything that vaguely looks like an optional argument
# (starts with a -) to getopts.
if [[ $1 = -* ]]; then
# Grab some options:
while getopts "$option_string" option; do
case $option in
a) ... ;;
# etc.
esac
done
# get rid of whichever options we've handled and reset OPTIND
shift $((OPTIND - 1))
OPTIND = 1
else
# Accumulate and ditch the positional argument:
positional+=("$1")
shift
fi
done

或者,您可以使用getopt(1)的GNU实现,它将为您完成所有这些,代价是使用一个稍微更烦人的接口。(至少,我觉得这很烦人,但YMMV。)

最新更新