使用case命令处理解析命令行参数的极端情况的正确方法

时间:2016-03-25 00:38:00

标签: bash

我有一个bash脚本,它接受三个命令行参数,例如脚本执行如下:script -c <value> -h <value> -w <value>。我想确保:

  • 参数顺序并不重要
  • 如果参数没有值,则打印错误消息
  • 如果缺少任何参数,则打印错误消息
  • 如果有未知参数,则打印错误信息

我通过以下case语句完成了这项工作:

#!/bin/bash

while :; do
  case "$1" in
    -h)
      [[ x${2%%-*} != x ]] || { echo "Value for "$1" missing!"; exit 1; }
      host="$2"
      shift 2
    ;;
    -w)
      [[ x${2%%-*} != x ]] || { echo "Value for "$1" missing!"; exit 1; }
      warning="$2"
      shift 2
    ;;
    -c)
      [[ x${2%%-*} != x ]] || { echo "Value for "$1" missing!"; exit 1; }
      critical="$2"
      shift 2
    ;;
    "")
      [[ $host && $warning && $critical ]] || { echo "One of the arguments is missing!"; exit 1; }
      break
    ;;
    *)
      echo "Unknow option"
      exit 1
    ;;
  esac
done

但是,也许case本身有一些高级选项可以避免所有[[ ]]测试?或者我可以使用另一种方法来处理命令行参数,如果我想确保上面描述的极端情况也被覆盖?

1 个答案:

答案 0 :(得分:0)

理想情况下,您应该使用getopts内置功能,但也有other ways。 Getopts是最便携和易读的选项,几乎可以自动处理所有“极端情况”。

while getopts c:h:w: arg; do
  case $arg in
    ( c )  critical="$OPTARG" ;;
    ( h )  host="$OPTARG" ;;
    ( w )  warning="$OPTARG" ;;
    ( \? ) exit 2 ;;
  esac
done
shift $((OPTIND-1))

if [ -z "$critical" ] || [ -z "$host" ] || [ -z "$warning" ]; then
  echo "One of the arguments is missing!"
  exit 1
fi

每个选项后跟一个冒号,表示它有一个强制参数。如果您有一个不使用参数的标志,请不要使用带冒号的选项。 POSIX getopts不支持带有可选参数的选项。

另请参阅my answer这个关于supporting long options的问题,https://stackedit.io/只关键字-选项,其参数由嵌套的case开关解析。以这种方式实现的长选项实际上可以支持可选参数。

我非常喜欢超载-h寻求帮助。假设您有一个帮助功能,请将其放在getopts循环之前:

# when the sole argument is -h, provide help
if [ "$*" = "-h" ]; then
  help
  exit 0
fi