使用“Bash严格模式”时如何解析Bash脚本的位置参数?

使用“Bash严格模式”时如何解析Bash脚本的位置参数?

Bash 严格模式定义如下:

#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

http://redsymbol.net/articles/unofficial-bash-strict-mode/

考虑以下 Bash 脚本中位置参数的解析:

#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

usage() {
  echo ""
  echo "usage:"
  echo "$0 [options]"
  echo "  -r | --redirect-uri:  redirect uri"
  echo "  -a | --app-role:      app role id"
  echo "  -h | --help:          help"
  echo ""
}

redirect_uri=""
app_role=""

while [ "$1" != "" ]; do
  case $1 in
  -r | --redirect-uri)
    shift
    redirect_uri="$1"
    ;;
  -a | --app-role)
    shift
    app_role="$1"
    ;;
  -h | --help)
    usage
    exit 0
    ;;
  *)
    usage
    exit 1
    ;;
  esac
  shift
done

...

这不适用于以下错误,例如:

$ ./app.sh -r https://example.net:8080/auth/callback -a 53b37b21-2c6e-4731-a5e5-15b98052c686        
./app.sh: line 18: $1: unbound variable

我认为原因是while条件中的最终检查, after shift, where$1未定义。

使用 Bash 严格模式时,如何终止while语句中的参数解析而不导致脚本崩溃?

答案1

您会收到unbound variable错误,因为您试图$1在未定义的情况下访问它,而在while循环的最后一次迭代之后它不会出现。因此,有问题的命令是您使用的测试while

[ "$1" != "" ]

相反,使用类似的东西

[ "${1+set}" = set ]

或者

[ -n "${1+set}" ]

参数扩展${parameter+word}将扩展为wordifparameter是一个现有变量(无论它是否具有非空值)。这个词set是任意选择的,但在某种程度上暗示了它的用途。

您还可以测试$#,它保存位置参数的数量:

[ "$#" -ne 0 ]

或者

[ "$#" -gt 0 ]

只要存在仍需要处理并从列表中移出的位置参数,这些算术测试都是正确的。

nounset这些变体中的任何一个都避免了与shell 选项 ( )施加的限制相冲突set -u

相关内容