Bash getopts: 如何识别负选项(-x- 或 +x)?

4

类似于this,但是在bash中实现。

我有一个现有的bash脚本,使用内置的getopts来识别-s(仅标志-无参数)。 我发现每次都要使用该选项,因此我希望将其设置为默认值,除非在命令行上指定了-s-+s。 但是,虽然ksh getopts可以处理+s, 但我在bash getopts手册中找不到这种能力。

我的当前解决方法是:

  1. 使用s:以便我可以通过$OPTARG="-"识别-s-; 或者
  2. 替换-s为不同的选项,例如-d(表示“不要”)。

然而,#1的问题在于如果我意外指定-s,它会吞下下一个参数,而#2的问题在于它使用了与我已经记住的开关字母不同的字母。我希望有一种简单的方法来解析bash中的-s-+s

  • util-linux getopt(1) 程序似乎也不支持+s。它可以处理可选参数,因此可能能够使用-s-。然而,我以前没有使用过getopt(1),因此希望您能给出指引,以免自己踩坑。
  • BashFAQ 035 建议“自行解析”。如果您已经编写了一个可以执行+s-s-的例程,我很想看看它。

我的当前参数解析循环非常基本:

while getopts "nthps" opt ; do
    case "$opt" in
        <other cases cut>
        (s)     saw_s="yes"
                ;;
    esac
done
shift $((OPTIND-1))
1个回答

2

负标志序列(+abcdef +g)与普通序列(-abcdef -g)不同,只有加号字符。因此,您可以简单地恢复+前缀的标志值。

第二种负序列形式很简单。只需剥离最后一个字符(-),并否定正常标志值。

示例

以下脚本接受所有提到的格式,例如:-ns -n -s -n- -ns- +ns +n +s

arglist='ns'

while (( $# )); do
  arg="$1"

  # Parse -abcdef- (negative form of -abcdef) options
  if [ "${arg:0:1}" = '-' -a "${arg#${arg%?}}" = '-' ]; then
    flag_val=no
    arg="${arg%?}" # -abcdef- becomes -abcdef
  elif [ "${arg:0:1}" = '+' ]; then
    flag_val=no
    arg="${arg/#+/-}"
  else
    flag_val=yes
  fi

  # OPTIND is the index of the next argument to be processed.
  # We are going to parse "$arg" from the beginning, so we need
  # to reset it to 1 before calling getopts.
  OPTIND=1

  while getopts "$arglist" opt "$arg"; do
    case "$opt" in
      s) saw_s="$flag_val" ;;
      n) saw_n="$flag_val" ;;
    esac
  done

  shift
done

# Set default values
: ${saw_s:=yes}
: ${saw_n:=no}

printf "saw_s='%s'\nsaw_n='%s'\n" "$saw_s" "$saw_n"

测试

$ ./pargs.sh
saw_s='yes'
saw_n='no'
$ ./pargs.sh -s
saw_s='yes'
saw_n='no'
$ ./pargs.sh +s
saw_s='no'
saw_n='no'
$ ./pargs.sh -s-
saw_s='no'
saw_n='no'
$ ./pargs.sh -s- +s -s
saw_s='yes'
saw_n='no'
$ ./pargs.sh -s +s
saw_s='no'
saw_n='no'
$ ./pargs.sh +s -s
saw_s='yes'
saw_n='no'
$ ./pargs.sh -s -s-
saw_s='no'
saw_n='no'
$ ./pargs.sh -sn
saw_s='yes'
saw_n='yes'
$ ./pargs.sh -sn -s-
saw_s='no'
saw_n='yes'
$ ./pargs.sh -sn +s
saw_s='no'
saw_n='yes'
$ ./pargs.sh +sn
saw_s='no'
saw_n='no'
$ ./pargs.sh -sn-
saw_s='no'
saw_n='no'
$ ./pargs.sh -sn- -n
saw_s='no'
saw_n='yes'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接