问:
一位同事最近在代码审查中声称,在如下结构中通常应该优先选择使用 [[ ]] 结构而不是 [ ]。
代码语言:javascript复制if [ "`id -nu`" = "$someuser" ] ; then
echo "I love you madly, $someuser"
fi
他无法提供一个合理的解释。这样的解释存在吗?
答:
在 Bash 脚本中使用 [[ ]] 相对于 [ ] 可以总结出以下几个优点:
1. 单词分割和通配符展开:在 [[ ]] 内部,变量扩展不会发生单词分割(根据空格或其它 IFS 字符将字符串拆分成单词)和文件名扩展(通配符展开)。这意味着下面使用 [[ ]] 的代码不需要引号来包围变量扩展:
代码语言:javascript复制if [[ $(id -nu) = $someuser ]]; then
echo "I love you, $someuser"
fi
而与 [ ] 相比,你需要小心地添加引号来防止变量扩展时发生单词分割或通配符展开:
代码语言:javascript复制# 正确使用引号以防止通配符展开和单词分割
if [ "$(id -nu)" = "$someuser" ]; then
echo "I love you, $someuser"
fi
2. 高级字符串匹配:[[ ]] 支持使用 == 和 != 操作符进行模式匹配,以及使用 =~ 进行正则表达式匹配(使用 POSIX 的 regcomp 和 regexec 接口),比如 [[ hello == hell? ]],结果为真。而 [ ] 不支持这些功能。
3. 逻辑运算符:使用 [[ ]],你可以在同一对括号内使用 && 和 || 进行逻辑运算。在 [ ] 中,你需要使用多组括号并使用 -a 和-o,或者使用外部逻辑运算符连接多个 [ ] 结构:
代码语言:javascript复制# 使用 [[ ]]
if [[ 条件1 && 条件2 ]]; then
# 执行某些操作
fi
# 使用 [ ]
if [ 条件1 ] && [ 条件2 ]; then
# 执行某些操作
fi
4. 安全的条件表达式:由于 [ ] 实际上是 test 命令的别名,某些表达式可能会意外地作为文件测试操作。在 [[ ]] 中,这种混淆的可能性较小。
总之,尽管 [[ ]] 不遵守 POSIX 标准,因此在 Bash 之外的环境中可移植性较差,但它确实为 Bash 脚本中的条件表达式提供了一个更强大的功能集。
参考文档:
- stackoverflow question 669452
- https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructs