如何编写一个以随机顺序获取参数和标志的函数?

如何编写一个以随机顺序获取参数和标志的函数?

我是 shell 新手,我试图编写一个接受常规参数的自定义函数,并解析提供的任何标志。

test_it() {
  flag1="false"
  flag2="false"

  while getopts "ab" opt; do
    case ${opt} in
    a) flag1="true" ;;
    b) flag2="true" ;;
    *) break ;;
    esac
  done
  echo $flag1 $flag2
  shift "$(($OPTIND - 1))"
  echo "Custom param: $1"
}

但是,如果我在标志后提供自定义参数,则此函数只能按我想要的方式工作。如果我要在标志之前提供自定义参数,它不会解析标志。

> test_it -ab foo
true true
Custom param: foo
> test_it foo -ab
false false
Custom param: foo
> test_it -a foo -b
true false
Custom param: foo

有没有一种方法可以使标志和参数无论顺序如何都能正确解析?换句话说,它应该true true在所有这三种情况下回显这两个标志,因为它们是在函数调用期间的某个时刻被调用的?这应该是可能的,因为我观察到函数喜欢rsync这样做。

答案1

是的:在函数中,在调用之前while getopts添加

local OPTIND OPTARG

每次都会将“计数器”重置为 0。


另请注意,这while getopts将在第一个非选项处停止。如果你想test foo -ab工作,你需要使用getopt(1)getopt示例脚本

test_it() {
    local tmp flag1=false flag2=false
    tmp=$(getopt -o 'ab' -n "$FUNCNAME" -- "$@")
    
    local rc=$?
    ((rc == 0)) || return $rc
    
    eval set -- "$tmp"
    
    while true; do
        case "$1" in
            '-a') flag1=true
                  shift
                  ;;
            '-b') flag2=true
                  shift
                  ;;
            '--') shift
                  break
                  ;;
            *)    echo Internal Error >&2
                  return 1
                  ;;
        esac
    done

    declare -p flag1 flag2
    echo "Remaining params:"
    printf "%s\n" "$@"
}
$ test_it foo -a bar -b
declare -- flag1="true"
declare -- flag2="true"
Remaining params:
foo
bar

$ test_it -a quz
declare -- flag1="true"
declare -- flag2="false"
Remaining params:
quz

$ test_it baz -b
declare -- flag1="false"
declare -- flag2="true"
Remaining params:
baz

$ test_it -c
test_it: invalid option -- c

$ test_it baz --ab
test_it: unrecognized option `--ab'

相关内容