bash中参数扩展为空字符串时处理不一致的技术疑问
Bash 参数扩展的异常行为:确认是 Bug
你碰到的这个问题确实是bash的bug,已经在bug-bash邮件列表中被其他用户确认,修复方案可以从bash devel分支的最新提交中获取。
核心问题复现
先看两个让你困惑的命令:
这条命令输出空行,符合预期:
bash -c 'echo "${1##*""}"' _ bar因为
${1##*}会扩展为空字符串,"${1##*}"和""的处理逻辑应该完全一致。但这条命令却输出了
bar,明显不符合预期:bash -c 'echo "${1##*"${1##*}}"' _ bar按道理,
${1##*}扩展后是空,所以整个表达式应该等价于"${1##*}",最终输出空行才对,但bash的处理却走了样。
其他Shell的一致表现
几乎所有主流sh实现都表现出符合预期的行为(执行后输出空行):
sh -c 'echo "${1##*"${1##*}}"' _ bar ash -c 'echo "${1##*"${1##*}}"' _ bar dash -c 'echo "${1##*"${1##*}}"' _ bar ksh -c 'echo "${1##*"${1##*}}"' _ bar ksh93 -c 'echo "${1##*"${1##*}}"' _ bar mksh -c 'echo "${1##*"${1##*}}"' _ bar posh -c 'echo "${1##*"${1##*}}"' _ bar yash -c 'echo "${1##*"${1##*}}"' _ bar zsh -c 'echo "${1##*"${1##*}}"' _ bar
而bash不管加不加--posix参数,都是唯一的例外:
bash -c 'echo "${1##*"${1##*}}"' _ bar # 输出结果: bar
进一步验证:无截断处理的场景
当内部的参数扩展不是${1##*}时,bash的行为又回到了符合预期的状态(输出空行):
bash -c 'echo "${1##*"${1+}}"' _ bar bash -c 'echo "${1##*"${2}}"' _ bar bash -c 'echo "${1##*"${2}}"' _ bar ''
结论与解决办法
- 定性:这绝对是bash的bug——在解析
${parameter##word}结构时,当word部分嵌套的参数扩展结果为空字符串,bash没有正确处理引号的拼接逻辑,导致word被错误解析为空,相当于完全跳过了##*的截断操作。 - 修复方式:这个bug已经被确认,你可以拉取bash devel分支的最新代码编译,就能获得修复后的版本。
- 临时 workaround:虽然你提到取消内部引号可能在特殊字符场景出问题,但如果需要临时解决,可以这样写:
更稳妥的方式是先把内部扩展的结果存到变量里再使用:bash -c 'echo "${1##*${1##*}}"' _ barbash -c 'empty=${1##*}; echo "${1##*$empty}"' _ bar
内容的提问来源于stack exchange,提问作者oguz ismail
相关产品推荐
相关产品推荐

