使用getopts读取作为最终位置放置的一个可选参数

时间:2015-03-03 22:22:50

标签: bash arguments getopts

我编写了一个bash脚本,它采用了灵活的参数,现在我想为每个参数添加一个可选参数(-l)。

我目前难以获得理想的行为。

我希望以下所有内容都能正确执行:

./Script.sh arg1 arg2 arg3 -l opt 
./Script.sh arg1 arg2 arg3
./Script.sh arg1 arg2 arg3 arg4 -l opt
./Script.sh arg1 arg2 arg3 arg4 arg5

问题是无法设置$OPTIND。 如果-l opt放在第一个参数之前,则以下循环有效。

while getopts ":l:" option
do
    case "$option" in
        t) 
            F_NAME=$OPTARG 
            ;;
    esac
done
shift $((OPTIND - 1))

但是,将可选-l作为最后一个参数是必需的。 最简单的方法是什么?

2 个答案:

答案 0 :(得分:2)

这是我发现使用带有getopts的可选参数的参数的技巧。

管理Janr Schampera在命令中可选参数的情况的方法是bash-hackers.org上的回复:

  if [[ $OPTARG = -* ]]; then
    ((OPTIND--))
    continue
  fi

(参见:页面深处的http://wiki.bash-hackers.org/howto/getopts_tutorial) 但它没有管理在命令末尾给出选项的情况。

在这种情况下,这被认为是错误的,因为没有给出参数,getoptsopt变量设置为''(冒号)和OPTARG到故障选项值。 因此,我们必须使用case $OPTARG管理“”案例。

让我们说我们编写一个有三个选项的脚本:

  • a:不带参数
  • b:带有必需参数
  • v:使用02的值设置详细程度。默认值为0,并且当使用-v调用脚本而没有参数或值不正确时使用的预设值。

这是代码:

#!/bin/bash

VERBOSITY=0 # default verbosity set to 0
PRESET_VERBOSITY=1 # preset verbosity when asked

while getopts :ab:v: opt; do
  case $opt in
    a)
      echo "manage option a"
    ;;
    b)
      echo "manage option b with value '$OPTARG'"
    ;;
    v)
      if [[ $OPTARG = -* ]]; then # Jan Schampera reply
        echo "set verbosity to PRESET (no value given, not last position)"
        VERBOSITY=$PRESET_VERBOSITY
        ((OPTIND--))
        continue
      fi

      if [[ "$OPTARG" =~ ^[0-2]$ ]]; then
        echo "set verbosity to $OPTARG (good value given)"
        VERBOSITY=$OPTARG
      else
        echo "set verbosity to PRESET (bad value given)"
        VERBOSITY=$PRESET_VERBOSITY
      fi
    ;;
    :)
      case $OPTARG in
        v)
          echo "set verbosity to PRESET (no value given, last option)"
          VERBOSITY=$PRESET_VERBOSITY
        ;;
      esac
    ;;
    \?)
      echo "WTF!"
    ;;
  esac
done

echo "**verbosity is set to $VERBOSITY**"

答案 1 :(得分:1)

getopts符合posix标准命令行语法,其中标志选项首先出现。因此,对于非标准情况使用起来并不容易。

但是,您可能有getopt(1)的Gnu实现(请参阅man 1 getopt),它可以处理置换选项标志以及长选项。但是,它并不像界面那么容易。

或者你可以自己解释一下这个论点。

for ((i=1; i<=$#; ++i)); do
  if [[ ${!i} == "-l" ]]; then
    ((++i))
    OPT_L=${!i}
  else
    # handle the argument (in "${!i]")
  fi
done

(注意:如果-l出现在参数列表的末尾,上面不会抛出错误;它只是将选项值设置为空字符串。如果这不合适,它可能不是然后插入一些错误检查。)