如何验证shell脚本中的参数数量(强制和可选)?

时间:2017-11-16 17:08:14

标签: linux bash shell getopts

我无法验证我的脚本参数。我试图为我的脚本实现5个强制参数和2个可选参数。这是我到目前为止所尝试的内容。

#!/bin/sh

if [ $# -lt 5 ] || [ $# -gt 7 ]
then
  echo "Please supply 5 or 6 or 7 parameters. Aborting."
  exit 1
fi

echo MP1 = "$1"
echo MP2 = "$2"
echo MP3 = "$3"
echo MP4 = "$4"
echo MP5 = "$5"

while getopts c:a: optionalargs
do
        case $optionalargs in
          c)copt=$OPTARG;;
          a)aopt=$OPTARG;;
          *)echo "Invalid arg";;
        esac
done

if [ ! -z "$copt" ]
then
    export CHAR_SET=$copt
fi

if [ ! -z "$aopt" ]
then
    export ADDITIONAL_FLAGS=$aopt
fi

shift $((OPTIND -1))

echo OP_C = "${CHAR_SET}"
echo OP_A = "${ADDITIONAL_FLAGS}"

问题是验证此脚本的参数总数,因为我可以总共有5或7个参数。提供-a additional -c character被视为9个参数。

./a.sh 1 2 3 4 5 -a additional -c character
Please supply 5 or 6 or 7 parameters. Aborting.

我对没有-的设计持开放态度,只要我能够同时拥有强制参数和可选参数。

如何正确验证?

2 个答案:

答案 0 :(得分:1)

每个以空格分隔的字符串都将被shell解释为新参数。你是否允许没有参数的-a标志或-c参数?假设那些需要跟随它们的东西,你实际上需要允许5或7或9个参数。 Getopts与初始shell参数解析分开。

除此之外,脚本看起来不错。对于质量检查,我建议Shellcheck

答案 1 :(得分:1)

首先:shell对可选参数和强制参数一无所知,不会处理以" - "开头的参数。特别是这样的事情。它只有一个"单词"的列表,它取决于你的脚本,以弄清楚它们的含义。 getopts命令可以帮助解析参数,但它处理的语法相当有限:

  • 选项以单个破折号开头,并且是单个字母(之后可能带有参数)。对于不接受参数的选项,您可以在单个短划线上堆叠多个选项(例如ls -la)。
  • 在所有选项之后,可以有许多位置参数(这些参数的含义被定义 - 顾名思义 - 通过它们在列表中的位置,例如第一,第二等)。

有许多语法扩展(主要是GNU约定),getopts 支持:

  • 在位置参数之后放置选项(例如ls filename -l)。选项必须始终排在第一位。
  • 长选项(多字母和/或双击,例如ls --all)。
  • 使用--将选项与位置参数分开。

因此,如果您想使用getopts - 样式可选参数,则需要将它们放在参数列表中的第一位。在解析它们时,你需要解析并从参数列表中删除它们(使用shift,然后再检查位置参数的数量,并使用$1等访问位置参数。您当前的脚本遇到了麻烦,因为它首先尝试处理位置参数,并且不能使用getopts(至少没有一些重型kluging)。

如果您需要更通用的参数语法,您可以使用getopt(请注意名称中缺少" s")。某些版本的getopt支持GNU约定,有些版本不支持。有些还有其他问题。国际海事组织这是一个未开封的最好的蠕虫。

另一种可能性是放弃-选项语法,并给脚本7位置参数,其中最后两个可以省略。这个问题是你不能省略第六个但是传递第七个(除非你愿意考虑第六个是空白等同于省略它)。这个代码看起来像这样:

if [ $# -lt 5 ] || [ $# -gt 7 ]
then
  echo "Please supply 5 or 6 or 7 parameters. Aborting."
  exit 1
fi

echo "MP1 = $1"
echo "MP2 = $2"
echo "MP3 = $3"
echo "MP4 = $4"
echo "MP5 = $5"

if [ -n "$6" ]; then
    # This will run if a sixth argument was specified AND it wasn't blank.
    export CHAR_SET=$6
    echo "OP_C = ${CHAR_SET}"
fi

if [ $# -ge 7 ]; then
    # This will run if a seventh argument was specified EVEN IF it was blank.
    # If you want to omit this for a blank arg, use the `-n` test instead.
    export ADDITIONAL_FLAGS=$7
    echo "OP_A = ${ADDITIONAL_FLAGS}"
fi

...然后使用例如

运行脚本
./a.sh 1 2 3 4 5 character additional    # Both optional args supplied
./a.sh 1 2 3 4 5 character               # Only first optional arg supplied
./a.sh 1 2 3 4 5 "" additional           # Only second optional arg supplied

或者,如果您真的想要更广泛的语法并且不想冒getopt命令变幻莫测的风险,那么您可以花费大量时间和精力编写自己的解析系统。国际海事组织这是一项比它更值得的工作。