如果未命名的参数在命名参数之前(“./foo unnamed -n named”),则getopts忽略所有参数

时间:2011-11-18 12:27:25

标签: bash command-line options getopts

我试图理解为什么getopts似乎忽略了所有参数,如果“unnnamed”参数在任何命名参数之前。

使用http://wiki.bash-hackers.org/howto/getopts_tutorial中的示例,

#!/bin/bash

while getopts ":a" opt; do
  case $opt in
    a)
      echo "-a was triggered!" >&2
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      ;;
  esac
done

观察结果:

$ ./opt_test
$ ./opt_test -a
-a was triggered!
$ ./opt_test -a -f
-a was triggered!
Invalid option: -f
$ ./opt_test a -a -f
$ ./opt_test a -a
$ ./opt_test a -f
$ ./opt_test lala -f
$ 

因此,在未命名的参数(没有破折号的参数)之前添加似乎会使getopts忽略所有参数。

为什么会这样,我该如何解决?我希望我的程序能够捕获这些内容并打印使用屏幕。

4 个答案:

答案 0 :(得分:3)

程序在遇到第一个非选项参数时停止处理选项是相当标准的行为。这通常就是你想要的。例如,想一想:

ssh someremotehost ls -l

如果ssh尝试在第一个非选项参数之后处理选项,则永远无法将参数传递给远程命令。 getopt支持的另一个标准是选项处理在--参数处明确停止,因此您可以执行以下操作来删除名为-f的文件:

rm -- -f

如果您真的想在命令行的任何位置处理选项,您可以编写自己的选项处理例程。这并不是那么困难,您也可以实现对长期权(--this-is-a-long-option)的支持。

答案 1 :(得分:2)

我使用的解决方法是将数组切片传递给getopts:

而不是:

while getopts ":a" opt; do

试试这个:

while getopts ":a" opt ${@:2}; do

这会传递getopts第二个到最后一个参数进行解析并正常工作以忽略第一个参数。

答案 2 :(得分:1)

引自getopts documentation

“以下任何一项都应标明选项的结尾:特殊选项” - “,查找不以” - “开头或遇到错误的参数。” < / p>

答案 3 :(得分:0)

要让选项出现在未命名(位置)参数之前,请使用shift后跟词进行清理,

e.g。有一个没有值的选项:

while getopts "u" opt; do
case $opt in
  u) USE_USERNAMES="TRUE"
  ;;
  \?) echo "Invalid option -$OPTARG" >&2
  ;;
esac
done

# Clean-up after arguments parsing
if test "$USE_USERNAMES"; then
  shift 
fi

或者,值为:

while getopts "s:" OPT; do
case $OPT in
  s) SUBMISSIONS="$OPTARG"
  ;;
  \?) echo "Invalid option -$OPTARG" >&2
      exit 1
  ;;
esac
done

# Clean-up arguments and assign default values AFTER arguments parsing
if test "$SUBMISSIONS"; then
  shift 2
else
  SUBMISSIONS="./logins.txt"
fi

# Move on to unnamed (positional) arguments
if ! test "$1"; then
  echo "ERROR: Required first argument missing"
  exit 1
fi

# Use arguments
echo "SUBMISSIONS: $SUBMISSIONS"
echo "FIRST ARG: $1"

<强>参考