当您在grep
命令中添加--ignore-case
选项时,很惊讶地发现搜索速度会降低50倍。我已经在两台不同的机器上进行了测试,并得到了相同的结果。我很想知道这种巨大性能差异背后的原因。
我还想找到一种替代grep
命令的方法,用于不区分大小写的搜索。我不需要正则表达式,只需要固定字符串搜索。首先,测试文件将是一个50MB的纯文本文件,其中包含一些虚拟数据,您可以使用以下代码生成:
创建test.txt
yes all work and no play makes Jack a dull boy | head -c 50M > test.txt
echo "Jack is no fun" >> test.txt
echo "Jack is no Fun" >> test.txt
演示
以下是速度变慢的演示。通过添加--ignore-case
选项,该命令变慢了57倍。
$ time grep fun test.txt
all work and no plJack is no fun
real 0m0.061s
$ time grep --ignore-case fun test.txt
all work and no plJack is no fun
Jack is no Fun
real 0m3.498s
可能的解释
在Google中搜索后,我发现有人讨论grep在UTF-8语言环境下速度变慢的问题。所以我进行了以下测试,并且确实提升了速度。我的电脑默认的语言环境是en_US.UTF-8
,所以将它设置为POSIX
似乎提高了性能,但现在当然无法正确地搜索Unicode文本,这是不可取的。而且它仍然比原来慢2.5倍。
$ time LANG=POSIX grep --ignore-case fun test.txt
all work and no plJack is no fun
Jack is no Fun
real 0m0.142s
替代方案
我们可以使用Perl,它比大小写敏感的grep快5.5倍,但仍然比上面的POSIX grep快两倍。
$ time perl -ne '/fun/i && print' test.txt
all work and no plJack is no fun
Jack is no Fun
real 0m0.388s
如果有人知道一种快速且正确的替代方法,并能解释一下,我会非常感激。
更新- CentOS
上面测试的两台机器都运行着Ubuntu 11.04(Natty Narwhal)和12.04(Precise Pangolin)。在一台CentOS 5.3的机器上运行相同的测试,产生了以下有趣的结果。这两种情况的性能结果几乎是相同的。现在,CentOS 5.3是在2009年1月发布的,运行grep 2.5.1,而Ubuntu 12.04运行的是grep 2.10。因此,在新版本中可能会有变化,并且在两个发行版中也有差异。
$ time grep fun test.txt
Jack is no fun
real 0m0.026s
$ time grep --ignore-case fun test.txt
Jack is no fun
Jack is no Fun
real 0m0.027s