zsh 手册页在其test
(aka [
) 部分明确建议不要使用它,并敦促读者[[
尽可能使用它。
这相关部分状态:
该命令尝试实现 POSIX 及其指定的扩展。不幸的是,语法中存在固有的歧义;特别是,测试运算符和类似的字符串之间没有区别。该标准尝试解决少量参数(最多四个)的问题;对于五个或更多参数,不能依赖兼容性。我们敦促用户尽可能使用
[[
不存在这些歧义的“ ”测试语法。
我想我也遇到过类似的 bash 建议,但是当我浏览 bash 手册页时,我找不到任何关于使用哪种形式([
或)的“官方”建议。 [[
(也许我错过了?)
有什么理由吗,除了向后兼容“旧 shell”之外
[
,在 bash 脚本中使用?或者换句话说,bash 持续[
存在[[
是有原因的吗?其他比向后兼容性?
答案1
但还是有一些细微的差别:
#!/bin/bash
eg=whatever
if [ $eg == what* ]; then # file glob test
echo '[]'
fi
if [[ $eg == what* ]]; then # pattern match test
echo "[[]]"
fi
除非当前目录中有一个名为“whatever”的文件,否则第一个测试将不会通过,因为匹配是针对当前目录内容的文件 glob,而第二个测试是实际的字符串模式匹配。
答案2
[
优先选择[[
if enough 的原因是它[
在不同的 bash 版本之间更稳定。
看man bash
:
兼容31
如果设置,bash 将其行为更改为版本 3.1 中 [[ 条件命令的 =~ 运算符的带引号参数。
兼容32
如果设置,当使用 [[ 条件命令的 < 和 > 运算符时,bash 会将其行为更改为 3.2 版关于特定于区域设置的字符串比较的行为。 bash-4.1 之前的 Bash 版本使用 ASCII 排序规则和 strcmp(3); bash-4.1 及更高版本使用当前语言环境的排序规则序列和 strcoll(3)。
兼容40
如果设置,则在使用 [[ 条件命令的 < 和 > 运算符(请参阅上一项)以及中断命令列表的效果时,bash 会将其行为更改为版本 4.0 的特定于区域设置的字符串比较。
也许对于有背景的用户来说也更常见一些ksh
。
关于性能的注意事项
'[[' 比 '[' 更快
- 对于单个调用,速度差异有没有可比的影响,并且您应该更喜欢内置的“[”。
- 如果您在更大的循环结构中,您可能会考虑将 '[' 替换为 '[['
对于测量,您可以使用以下比较脚本
let upperBound=$1
echo "check [, ${upperBound} iterations"
let i=0
time while [ $i -lt ${upperBound} ] ; do let i++ ; done
echo; echo;
echo "check [[, ${upperBound} iterations"
let i=0
time while [[ $i < ${upperBound} ]] ; do let i++ ; done
比较脚本的结果
检查 [,1000 次迭代
真实 0m0.031s
用户 0m0.028s
系统 0m0.004s检查 [[,1000 次迭代
真实 0m0.000s
用户 0m0.000s
系统 0m0.000s