Bash参数替换中${var=default}与${var-default}有什么区别
Bash参数替换两类语法的核心差异
你之前测试未发现差异,核心是测试场景没有覆盖「原变量后续是否被复用」「变量已赋值为空字符串」两个关键边界,两类语法的实际规则差异非常明确:
两类语法的本质区别:是否修改原变量
${parameter-default}、${parameter:-default}是纯取值逻辑:仅在满足触发条件时,将default作为当前表达式的返回值,全程不会修改parameter本身的存储值,表达式执行完原变量状态不变。${parameter=default}、${parameter:=default}是带副作用的赋值逻辑:满足触发条件时,除了将default作为当前表达式的返回值,还会直接把default赋值给parameter变量,后续代码再调用该变量时,拿到的就是default值。
带冒号与不带冒号的触发条件区别
两种写法的触发阈值和后面跟的符号(-/=)无关,只和有没有冒号有关:
- 不带冒号版本:仅当
parameter完全未声明、未被设置过的时候,才会触发default逻辑;如果变量已经被赋值,哪怕赋值是空字符串""、数值0这类逻辑假值,都不会触发default。 - 带冒号版本:触发范围更宽,只要
parameter未设置,或者parameter的值为空字符串,就会触发default逻辑。
可直接复现差异的测试代码
你直接在shell里执行下面的代码,就能立刻看到行为区别:
# === 测试1:核心赋值行为差异 === unset test_var echo "1. 用\${test_var-default}取值结果:${test_var-default}" echo "2. 执行-语法后原变量值:'$test_var'" # 输出为空,原变量未被修改 unset test_var echo "3. 用\${test_var=default}取值结果:${test_var=default}" echo "4. 执行=语法后原变量值:'$test_var'" # 输出为default,原变量已被赋值 # === 测试2:带/不带冒号的触发阈值差异 === test_var="" # 显式给变量赋值为空字符串 echo "5. 不带冒号\${test_var-default}结果:${test_var-default}" # 输出空,变量已设置不触发 echo "6. 带冒号\${test_var:-default}结果:${test_var:-default}" # 输出default,空值触发替换 echo "7. 不带冒号\${test_var=default}结果:${test_var=default}" # 输出空,变量已设置不触发赋值 echo "8. 带冒号\${test_var:=default}结果:${test_var:=default}" # 输出default,空值触发赋值 echo "9. 执行:=语法后原变量值:'$test_var'" # 输出default,原变量已被修改
你之前测试没看到差异,大概率是只观察了表达式当前行的返回值,没有检查表达式执行后原变量的状态,且测试时没有覆盖变量被赋值为空的场景——在「变量完全未设置、且你只需要当前表达式的返回值、后续不会再用到该变量」的场景下,两类语法的返回结果确实完全一致,很容易误以为没有区别。
内容的提问来源于stack exchange,提问作者Xiang.Bao
相关产品推荐
相关产品推荐

