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

相关内容