Bash中使用[[做字符串相等比较时为何仍要给两字符串前置字符?
结论
在使用[[关键字进行字符串比较时,前置X字符的写法完全没有必要,属于POSIX test/[命令时代遗留的冗余编码习惯。
为什么[比较时需要加前缀
要搞清楚这个问题,首先要明确[和[[的本质差异:
[不是语法关键字,是和ls、echo一样的普通内置命令(多数系统还存在独立的/usr/bin/[外部命令),它完全按照普通命令的规则解析参数:- 如果待比较的变量展开后是空值,会导致参数缺失,触发语法错误。比如
VAR=""时,[ $VAR = "yes" ]展开后等价于[ = "yes" ],命令拿到的第一个参数是=,直接报错。 - 如果变量值以
-开头,会被[识别为命令选项,完全打乱判断逻辑。比如VAR="-n"时,[ $VAR = "yes" ]会被解析为「判断字符串"yes"长度非0」,和原本比较两个字符串是否相等的逻辑完全无关。
- 如果待比较的变量展开后是空值,会导致参数缺失,触发语法错误。比如
给比较两侧的字符串都加上固定前缀X,就能保证展开后的参数永远不会是空值、也永远不会以-开头,从根源上避免上述参数解析错误,这就是这个技巧最初的应用场景。
为什么[[比较时不需要这个技巧
[[是现代shell(bash、ksh、zsh等)提供的专用条件判断语法关键字,shell对它的解析是特殊处理的,不会走普通命令的参数拆分、选项识别逻辑:
==两侧的内容会被明确识别为待比较的字符串操作数,哪怕变量值为空、或者以-开头,也不会被当成缺失参数或者命令选项处理。
你可以直接运行下面的测试代码验证,所有写法在支持[[的shell中都能正常运行、判断逻辑完全正确,不需要加任何前缀:
# 变量为空的场景 NODENAME="" if [[ $NODENAME == "Node.js 10.x" ]]; then echo "匹配到Node.js 10.x" fi # 变量值以-开头的场景 NODENAME="-n" if [[ $NODENAME == "-n" ]]; then echo "匹配到-n" fi
为什么现有脚本还保留这种写法
NodeSource安装脚本里的写法纯粹是历史习惯遗留:很多有多年shell编写经验的开发者在POSIX [命令的坑里待久了,形成了肌肉记忆,哪怕写仅支持bash的脚本、用[[做判断,也会顺手加上前缀。这种写法不会改变相等比较的结果,不会引发错误,只是完全冗余而已。
补充说明:如果你的脚本需要兼容POSIX标准、必须使用
[做判断,加前缀的技巧依然是有效的,不过现代POSIX兼容shell中只要给变量加双引号(比如[ "$VAR" = "yes" ])就已经能避免空参数问题,加X属于更早期的系统兼容写法。
内容的提问来源于stack exchange,提问作者Pedro A
相关产品推荐
相关产品推荐

