如何在 bash 脚本中混合普通参数和标记参数?

如何在 bash 脚本中混合普通参数和标记参数?

例如,gcc 接受不带任何标志的输入文件和带有以下-o标志的输出文件:

gcc input.c -o output.out

或者

gcc -o output.out input.c

我正在创建一个随机密码生成器 bash 脚本,用户应该能够分别使用-s-l-u标志指定特殊字符、小写字符和大写字符的数量。他们还应该能够在没有任何标志的情况下指定密码的长度。

用法示例:

./randompassword.sh -s2 -u2 -l3 16

应表示包含 2 个特殊字符、2 个大写字符、3 个小写字符且长度为 16 的密码。

我可以getopts像这样解析标志:

while getopts s:l:u: flag
do
    case "${flag}" in
        s) special=${OPTARG};;
        l) lower=${OPTARG};;
        u) upper=${OPTARG};;
    esac
done

但是我不知道如何获取没有标志的长度参数。

我尝试使用$1,但这个参数应该能够位于命令中的任何位置,就像 gcc 示例一样。

答案1

getopts一旦到达非选项参数,就停止解析参数列表。也就是说,它在从左到右迭代选项参数时返回成功,然后在第一个非选项上返回失败。所以正确的用例是put options and their arguments on the command line before any non-option arguments.

getops然后教程会显示一个命令shift $((OPTIND - 1))。该while循环迭代选项参数,然后将shift它们从位置变量中删除,将非选项参数(如果有)保留在$@.

在代码中,使用教程中的变量:

while getopts ':s:l:u:' OPTION
do
  case "${OPTION}" in
    s) special=${OPTARG};;
    l) lower=${OPTARG};;
    u) upper=${OPTARG};;
   \?) echo "$0: Error: Invalid option: -${OPTARG}" >&2; exit 1;;
    :) echo "$0: Error: option -${OPTARG} requires an argument" >&2; exit 1;;
  esac
done
shift $((OPTIND - 1))
# now the positional variables have the non-option arguments
echo "${1}"

对于示例命令 ( ./randompassword.sh -s2 -u2 -l3 16),输出为16

:我在 getopts 字符串中添加了一个前导,因为它为您提供了“静默错误报告”,这使您的脚本可以捕获错误并发出更友好的投诉。这就是我在语句中添加的额外两个选项的功能case

如果用户违反规则并键入选项参数非选项参数,后面的选项参数不会在while上面的循环中被解析。它/它们将出现在$@包含剩余位置参数的数组中。如果用户遵循准则并在非选项参数之前键入所有选项参数,则在循环和命令完成$@后数组将具有非选项参数。whileshift

根据您对非选项参数输入顺序的担忧,要么您的脚本需要严格的顺序,您的用户必须遵循该顺序(否则他们会收到错误),要么您的脚本不需要它们的特定顺序,并且必须使用其他解析方法来弄清楚如何使用它们。

但在我看来,无序的参数就是我们有选项字母的原因。其余参数是有序的,否则它们将具有选项字母。不过,这只是我的意见。

相关内容