Bash判空设默认值和参数解析

199 阅读1分钟

变量判空设默认值

Shell 脚本中需要给某个变量赋值时,若数据来源不可控(如:用户输入、文件列表、环境变量),通常需要给变量设置一个默认值以方便对数据同一处理。Bash 中有多种语法支持设置这样的默认值:

  1. 为空返回默认值:${var:-def}:若var为空返回'def'
  2. 为空设置默认值:${var:=def}:若var为空将它置为'def'并返回
  3. 非空返回指定值:${var:+flag}:若var不为空时返回'flag',用于测试变量是否存在
  4. 判空断言:${var:?msg}:若var不为空返回其值,为空时输出var:msg并中断执行,同断言
    • 省略msg时输出var: parameter null or not set.

命令参数解析

Bash 命令在使用中通常有 3 种传参方式:

  1. 直接使用位置参数,如cmd status,其中入参status在函数 cmd 中可使用位置参数$1获取。
  2. 使用 Bash 内置短格式参数解析工具getopts,如cmd -v -f filename.txt
  3. 使用非标准 Unix 命令getopt解析长格式参数,如cmd --version --file filename.txt

特别的,大多数 Linux 的发行版都带了getopt工具,但getopt的旧版本 BUG 不少,这些 BUG 在新的增强版本中被修复(执行getopt -T; echo $?输出4表示该版本为增强版)。比如 MacOS 自带的 getopt 为旧版本,可使用 brew 安装增强版:brew install gnu-getopt 安装后将可执行文件加入 PATH:echo -e '\nexport PATH="/usr/local/opt/gnu-getopt/bin:$PATH"\n' >> ~/.bash_profile

总结

当编写 Bash 脚本读取用户输入的指令时,位置参数不利于功能拓展,长指令参数输入过于繁琐且依赖外部环境不利于代码移植,内置的getopts可作为中庸之道而被视为较优选择;且通常在指令参数解析过程中配合变量判空和设默认值写法,如:

#!/usr/bin/env bash

# 解析短格式参数 -a -f input
while getopts 'af:c:' OPT; do  # 参数键存入变量 OPT
    case "$OPT" in
    a)
        echo "a is open" # 获取无值参数
        ;;
    f)
        echo "f is $OPTARG" # 获取有值参数,参数值在内置变量 OPTARG 中
        ;;
    ?) # 其他配置项,如 -x
        echo "usage: $(basename $0) [-a] [-f xxx]" >&2
        exit 1 # 退出脚本,并将结果变量 $? 置为1
        ;;
    esac
done
# $OPTIND 在首次执行时是1之后每次解析后累加;通过shift可将短格式参数弹出,保持此后的参数从位置 $1 开始
shift "$(($OPTIND - 1))"