Bash:确保变量已设置且不覆盖已有值的两种写法对比
Bash中
${foo:=}与foo=${foo+$foo}的对比(开启set -u时) 核心作用一致
两种写法的最终目的都是确保变量foo已被设置(避免set -u下的未定义变量报错),同时保留foo已有的值(包括空字符串):
: ${foo:=}:利用空命令:执行参数扩展,若foo未设置或为空,则将其设为空字符串;若foo已有值,则无变化。foo=${foo+$foo}:直接通过参数扩展赋值,若foo已设置(无论是否为空),则将其赋值为自身;若foo未设置,则赋值为空字符串。
foo=${foo+$foo}的优势
写法更直观:
这是一个直接的赋值语句,不需要依赖空命令:,对不熟悉Bash特殊命令用法的开发者来说,一眼就能看懂是在维护foo的状态,而: ${foo:=}里的空命令容易让人困惑其作用。语义更清晰:
明确表达“当foo存在时保留原值,不存在时设为空”的逻辑,相比借助空命令间接实现赋值,语义上更直接对应需求。
二者行为不同的边缘场景
1. 操作只读变量时
如果foo是只读变量且已设置:
: ${foo:=}:不会触发报错,因为参数扩展检测到foo已有值,不会尝试修改它。foo=${foo+$foo}:会直接报错,因为这是一个赋值操作,即使赋值的是自身,Bash也不允许修改只读变量。
如果foo是只读变量且未设置:
两者都会触发报错——: ${foo:=}会试图给未设置的只读变量赋值,foo=${foo+$foo}同样是给只读变量赋值,均违反只读限制。
2. 操作数组变量时
Bash中数组变量和普通变量的处理逻辑不同:
: ${foo:=}:会将数组变量当作普通变量处理。如果foo是未设置的数组,执行后foo会变成值为空的普通变量,而非数组类型。foo=${foo+$foo}:若foo是已设置的数组,$foo等价于${foo[0]}(取数组第一个元素),因此执行后foo会被转换成普通变量,值为原数组的第一个元素,丢失其他数组元素;若foo是未设置的数组,同样会变成值为空的普通变量。
简单来说,两种写法都不适合处理数组变量,但foo=${foo+$foo}会直接破坏数组结构,而: ${foo:=}只是将未设置的数组转为普通变量,行为略有差异。
3. 特殊位置参数的处理
如果用这两种写法操作Bash的特殊位置参数(比如$1):
: ${1:=}:是合法的写法,可以确保位置参数$1被设置(若未传入则设为空)。1=${1+$1}:直接报错,因为位置参数是只读的,无法通过赋值语句修改。
内容的提问来源于stack exchange,提问作者barefootcoder
相关产品推荐
相关产品推荐

