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

Using getopts to read one optional parameter placed as final place

我写了一个 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 作为最后一个参数是必需的。 实现此目标的最简单方法是什么?

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 出现在参数列表的末尾,上面不会抛出错误;它只是将选项值设置为空字符串。如果那不合适,它可能不是,然后插入一些错误检查。)

这是我发现的一个技巧,可以在 getopts 中使用带有可选参数的参数。

Jan 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**"