0

假设我正在getopts使用选项字符串 ":a:b" 在 Bash 脚本中运行,并且我提供了以下命令行参数:

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

“foo”的实例是该选项的预期参数,a并且该选项b没有预期参数。但是,“bar”的实例和“zappo”的实例都是不可接受的getopts。运行后getopts,如何回显包含所有不可接受参数列表的变量?我怎样才能生成列表“bar 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}"
4

1 回答 1

1

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

utility -a foo bar -b bar zappo

utility不会解释-b为命令行标志。如果-a接受一个参数, thenbar将是第一个位置参数,然后将有另外三个位置参数,-bbarzappo

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

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

如果您想使用getoptsGNU 样式的选项处理,您必须自己进行置换。例如,您可以执行以下操作:

# 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

或者,您可以使用 的 GNU 实现getopt(1),它会为您完成所有这些工作,但代价是界面稍微有点烦人。(至少,我觉得它很烦人,但是 YMMV。)

于 2013-12-27T01:05:25.517 回答