我在 korn shell 脚本中找到了这一行:
var=${var:-/temp}
我能够弄清楚它在做什么
$ var=/data
$ var=${var:-/temp}
$ echo $var
/data
$ var=
$ echo $var
$ var=${var:-/temp}
$ echo $var
/temp
它比检查值然后分配有优势吗?
答案1
它更加精简;您可以用一个简单的命令而不是两个命令(例如[[ -z $var ]] && var=/temp
)或复杂的命令(例如
if [[ -z $var ]]
then
var=/temp
fi
此外,它不需要将条件值分配给变量。例如,
#!/bin/sh
prog="$1"
# Do sanity checks & input validation here.
cc "$prog" -o "${2:-$(basename "$prog")}"
如果调用为comp foo.c
,它将编译foo.c
并将编译后的输出写入foo
.但comp foo.c fu
会编译foo.c
并将编译后的输出写入fu
.
如果您想使用具有默认值的多个参数,这一点变得尤其重要:
一些命令${1:-默认值1${2:-默认值2${3:-默认值3${4:-默认值4${5:-默认值5} ${6:-默认值6${7:-默认值7${8:-默认值8${9:-默认值9}
如果采用其他方式,则需要大约 18 个命令来设置参数。
在不需要将条件值分配给变量的情况下如何使用此功能的另一个示例是想要让用户编辑文件的脚本:
#!/bin/sh ⋮ 文件=某物 ⋮ “$(编辑器:-vi}”“$文件”
它会调用用户最喜欢的编辑器(通过EDITOR
环境变量指定),或者vi
如果用户未指定编辑器。
答案2
存在三种情况:var
最初可能未设置、为空或非空。在前两种情况下,它设置为/temp
;在最后一种情况下,它被单独保留。
做同样事情的另一种方法是
: "${var:=/temp}"
我更喜欢那个,因为任务链更清晰,但这是一个美观问题。
在正常设置下,这相当于
if [ -z "$var" ]; then var="/temp"; fi
这可以说更清楚了。然而,语法${var:-…}
or${var:=…}
有一个优点:它甚至可以在 下工作,如果未设置,set -u
则会导致$var
错误。var
其优点set -u
是可以很容易地发现由于错误输入变量名称或忘记在某些条件下定义变量而导致的错误。但是,它只能与不假定始终可以扩展未设置变量的脚本一起使用。
答案3
它是紧凑的习语。你可以使用它排队执行命令的位置:
cmd "${arg1}" "${arg2}" "${arg3:-42}"
或在程序开始时(或作为函数中的第一个语句)断言参数接口(使用:
命令):
: "${1:?} ${2:?}"
或检查并将其分配给您在程序或相应操作中操作的语义命名变量。功能:
foo=${1:?} bar=${2:?} baz=${3:-42}
其中前两个参数(在本例中)是强制性的,如果未提供,第三个参数有一个默认值(上面是“42”)。
如果涉及的不是位置参数而是变量,您还可以使用相关的构造${var:=val}
(或 resp. )来实现此目的:${var=val}
: "${foo:=${1:?}} ${bar:=${2:?}} ${baz:=${3:-42}}"
该${var:-42}
习语还有一个变体${var-42}
(即没有:
冒号)区分 未设置参数来自空的参数;test
构造不能直接区分空的变量来自未设置变量。
答案4
它不是“过度检查” - 它是“默认值”,换句话说,如果未设置值(或为空),则使用默认值。