【问题标题】:Warnings for invalid options无效选项的警告
【发布时间】:2022-01-15 01:32:56
【问题描述】:

我有一个 bash 函数,允许用户设置选项和参数。

heading [OPTIONS] PARAM...

我已经指定了以下选项

-V, --version, -v, --verbosity, -u, --usage, -h, --help
--vlt, --blu, --grn, --ylw, --orn, --pur, --red, --wht, -mSTY

如果无效选项被可用的功能选项包围,我想针对无效选项发出警告。

这很好

heading --vlt -m1 PARAMS

这也很好,因为 -adv 出现在所有可用选项之后

heading --vlt -m1 -adv Din

但这需要一个警告,因为 --adv 出现在可用选项 -m1 之前

heading --vlt --adv -m1 Din

这里列出了函数

copt ()
{
 while (( $# > 0 )); do
  case $1 in
   ("-V"|"--version") shift ; return 0 ;;
   ("-v"|"--verbosity") vb=1 ; shift ;;
   ("-u"|"--usage") usg=1 ; shift ; return 0 ;;
   ("-h"|"--help") shift ; return 0 ;;
   ("--vlt") vlt=$(tput setaf 57) ; shift ;;
   ("--blu") blu=$(tput setaf 12) ; shift ;;
   ("--grn") grn=$(tput setaf 2) ; shift ;;
   ("--ylw") ylw=$(tput setaf 3) ; shift ;;
   ("--orn") orn=$(tput setaf 166) ; shift ;;
   ("--pur") pur=$(tput setaf 93) ; shift ;;
   ("--red") red=$(tput setaf 1)  ; shift ;;
   ("--wht") wht=$(tput setaf 7)  ; shift ;;
   ("-m"*)   sty="${1#-m}" ; shift ;;
   ("--") shift ; break ;;
   (*) break ;;
  esac
 done
}

【问题讨论】:

  • 一个带有帮助信息的函数?无论如何,尚不清楚您对“可用选项”的标准是什么,并且关于选项处理的许多问题可能已经回答了您的问题,无论它可能是什么。提问前请先搜索,如果您仍需要帮助,请edit 说明您真正想要什么以及您已经尝试过什么。
  • 添加了更多细节。如果在有效选项之间出现无效选项,我只想要一个警告,不包括最后的无效选项。
  • -adv--adv 在您的问题中是否故意不同?如果是这样,那么以 1 - 与 2 -s 开头的字符串对您的问题有什么影响?如果没有,请解决您的问题。

标签: bash options


【解决方案1】:

通过循环参数,您基本上是在强迫自己接受第一个非选项参数之后的任何内容,即使它不是受支持的选项。你可以做的是循环两次参数,或者在最后一个有效选项之后循环剩余的参数,并警告第一个非选项参数之后的任何内容一个选项。

草稿:

copt ()
{
 while (( $# > 0 )); do
  case $1 in
   ("-V"|"--version") shift ; return 0 ;;
   ("-v"|"--verbosity") vb=1 ; shift ;;
   ("-u"|"--usage") usg=1 ; shift ; return 0 ;;
   ("-h"|"--help") shift ; return 0 ;;
   ("--vlt") vlt=$(tput setaf 57) ; shift ;;
   ("--blu") blu=$(tput setaf 12) ; shift ;;
   ("--grn") grn=$(tput setaf 2) ; shift ;;
   ("--ylw") ylw=$(tput setaf 3) ; shift ;;
   ("--orn") orn=$(tput setaf 166) ; shift ;;
   ("--pur") pur=$(tput setaf 93) ; shift ;;
   ("--red") red=$(tput setaf 1)  ; shift ;;
   ("--wht") wht=$(tput setaf 7)  ; shift ;;
   ("-m"*)   sty="${1#-m}" ; shift ;;
   ("--") shift ; break ;;
   (*) break ;;
  esac
 done
 local arg validopt invalidopt
 for arg; do
  case $arg in
   "-V"|"--version" \
   "-v"|"--verbosity" \
   "-u"|"--usage" \
   "-h"|"--help" \
   "--vlt" \
   "--blu" \
   "--grn" \
   "--ylw" \
   "--orn" \
   "--pur" \
   "--red" \
   "--wht" \
   "-m"*) validopt=$arg;;
   "-"*)  invalidopt=$arg;;
  esac
  if [[ $validopt && $invalidopt ]]; then
    echo "copt: cannot have invalid option $invalidopt before $validopt" >&2
    exit 1 # or whatever
  fi
 done
}

这是相当重复和笨拙的,我真的不建议偏离像这样的 de facto 选项处理约定。让第一个无效选项参数的函数 abort 更容易预测和使用,特别是因为您已经支持 -- 来表示选项结束。

【讨论】:

  • 如果调用仍然连贯,我无法中止无效选项。该功能旨在尽可能多地进行。
  • 我认为我们正在通过在最后一个有效选项之后循环剩余参数来解决问题。我同意这有点重复。
【解决方案2】:

我可能会创建一个关联数组,将意外参数映射到它们在 args 列表中出现的位置,并在初始循环之后处理它们(未经测试的伪代码):

declare -A unxArgs
while whatever; do
    (( ++argCnt ))
    gotUnxArg=0
    case $arg in
       --foo)  do good arg stuff ;;
       --bar)  do good arg stuff ;;
       *)      gotUnxArg=1 ;;
    esac
    if (( gotUnxArg == 0 )); then
        lastGoodArgPos="$argCnt"
    else
        unxArgs["$arg"]="$argCnt"
    fi
done

for unxArg in "${!unxArgs[@]}"; do
    argPos="${unxArgs[$unxArg]}"
    if (( argPos < lastGoodArgPos )); then
        echo "the sky is falling" >&2
    fi
done

【讨论】:

    猜你喜欢
    • 2018-11-05
    • 2017-05-31
    • 2022-11-11
    • 2015-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-27
    • 1970-01-01
    相关资源
    最近更新 更多