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

如何生成Bash中getopts无法接受的参数列表?,bash,arguments,options,getopts,Bash,Arguments,Options,Getopts,假设我正在Bash脚本中运行带有选项字符串“:a:b”的getopts,并提供以下命令行参数: ./script.sh -a foo bar -b bar zappo “foo”的实例是选项a的预期参数,而选项b没有预期参数。但是,getopts不能接受“bar”和“zappo”的实例。在运行getopts之后,如何回显包含所有不可接受参数列表的变量?我怎样才能制作“bar zappo”列表?谢谢 以下是一些代码,以方便您使用: #!/bin.bash option_string=":a:b"

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

./script.sh -a foo bar -b bar zappo
“foo”的实例是选项
a
的预期参数,而选项
b
没有预期参数。但是,
getopts
不能接受“bar”和“zappo”的实例。在运行
getopts
之后,如何回显包含所有不可接受参数列表的变量?我怎样才能制作“bar 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}"
#/宾·巴什
option_string=“:a:b”
意外的_参数=“”
OPTIND=1
而getopts“${option\u string}”选项;做
中的案例${options}
(a)
echo“-a由参数${OPTARG}“>&2#输出到STDERR触发
;;
(b)
回显“-b触发”>&2#输出到STDERR
;;
\?)
echo“无效选项:-${OPTARG}”>&2#输出到STDERR
;;
以撒
#
完成
echo“意外参数:${意外参数}”

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

utility -a foo bar -b bar zappo
实用程序
不会将
-b
解释为命令行标志。如果
-a
接受一个参数,那么
bar
将是第一个位置参数,然后还有三个位置参数,
-b
bar
zappo

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

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

如果您想将
getopts
与GNU风格的选项处理一起使用,您必须自己进行排列。例如,您可以这样做:

# 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)