我在bash (3.00) shell脚本中有一大堆关于变量的测试,如果变量没有设置,那么它会分配一个默认值,例如:

if [ -z "${VARIABLE}" ]; then 
    FOO='default'
else 
    FOO=${VARIABLE}
fi

我似乎记得在一行中做这件事有一些语法,类似于三元运算符,例如:

FOO=${ ${VARIABLE} : 'default' }

(虽然我知道这行不通……)

是我疯了吗,还是真的有这样的东西存在?


当前回答

FWIW,你可以像这样提供一个错误消息:

USERNAME=${1:?"Specify a username"}

这将显示如下消息,并以代码1退出:

./myscript.sh
./myscript.sh: line 2: 1: Specify a username

一个更完整的例子:

#!/bin/bash
ACTION=${1:?"Specify 'action' as argv[1]"}
DIRNAME=${2:-$PWD}
OUTPUT_DIR=${3:-${HOMEDIR:-"/tmp"}}

echo "$ACTION"
echo "$DIRNAME"
echo "$OUTPUT_DIR"

输出:

$ ./script.sh foo
foo
/path/to/pwd
/tmp

$ export HOMEDIR=/home/myuser
$ ./script.sh foo
foo
/path/to/pwd
/home/myuser

$ACTION接受第一个参数的值,如果为空则退出 $DIRNAME是第二个参数,默认为当前目录 $OUTPUT_DIR是第三个参数,或者$HOMEDIR(如果有定义),else, /tmp。这适用于OS X,但我不确定它是否可移植。

其他回答

还有一种更简洁地表达“if”结构的方法:

FOO='default'
[ -n "${VARIABLE}" ] && FOO=${VARIABLE}

如果变量相同,则

: "${VARIABLE:=DEFAULT_VALUE}"

如果没有定义,则将DEFAULT_VALUE赋值给VARIABLE。

内置冒号(:)确保不执行变量结果 双引号(")可以防止通配符和分词。

参见Bash手册中的章节3.5.3,Shell参数扩展。

可以像这样链接默认值:

DOCKER_LABEL=${GIT_TAG:-${GIT_COMMIT_AND_DATE:-latest}}

例如,如果$GIT_TAG不存在,则取$GIT_COMMIT_AND_DATE -如果不存在,则取"latest"

FWIW,你可以像这样提供一个错误消息:

USERNAME=${1:?"Specify a username"}

这将显示如下消息,并以代码1退出:

./myscript.sh
./myscript.sh: line 2: 1: Specify a username

一个更完整的例子:

#!/bin/bash
ACTION=${1:?"Specify 'action' as argv[1]"}
DIRNAME=${2:-$PWD}
OUTPUT_DIR=${3:-${HOMEDIR:-"/tmp"}}

echo "$ACTION"
echo "$DIRNAME"
echo "$OUTPUT_DIR"

输出:

$ ./script.sh foo
foo
/path/to/pwd
/tmp

$ export HOMEDIR=/home/myuser
$ ./script.sh foo
foo
/path/to/pwd
/home/myuser

$ACTION接受第一个参数的值,如果为空则退出 $DIRNAME是第二个参数,默认为当前目录 $OUTPUT_DIR是第三个参数,或者$HOMEDIR(如果有定义),else, /tmp。这适用于OS X,但我不确定它是否可移植。

如果你想在If -then-else语句中使用一行代码,那么我们可以考虑重写:

if [ -z "${VARIABLE}" ]; then 
    FOO='default'
else 
    FOO=${VARIABLE}
fi

分号:

if [ -z ${VARIABLE} ]; then FOO=`default`; else FOO=${VARIABLE}; fi

或者,如果你使用布尔操作符,你可以删除if-then-else-fi关键字,例如:

[ -z "${VARIABLE}" ] && FOO='default' || FOO=${VARIABLE}

概括来说,布尔运算符模式是:

conditional && then_command || else_command