我很惊讶地看到,当您将--ignore-case选项添加到grep中时,它可以将搜索速度降低50倍。我在两台不同的机器上测试过,结果是一样的。我很想找出一个巨大的性能差异的解释。
我还想看到一个代替grep的命令,用于不区分大小写的搜索。我不需要正则表达式,只需要固定的字符串搜索。首先,测试文件将是一个带有一些虚拟数据的50 MB纯文本文件,您可以使用以下代码来生成它:
创建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可能的解释
在搜索周围,我发现了一个关于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.142sAlternatives
我们可以使用Perl代替它更快,但仍然比区分大小写的grep快5.5倍。而上面的POSIX大约是速度的两倍。
$ 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 ( Narwhal),另一台12.04 (精确穿山甲)。在CentOS 5.3计算机上运行相同的测试会产生以下有趣的结果。两种情况的性能结果基本一致。现在,CentOS 5.3于2009年1月发布,an运行grep2.5.1,Ubuntu12.04运行grep2.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发布于 2012-12-11 12:01:16
我认为这个bug报告有助于理解为什么它是缓慢的:
发布于 2013-01-09 13:44:47
这是由于grep (在UTF-8语言环境上)经常访问文件“/usr/lib/locale/locale-归档”和“/usr/lib/gconv/gconv-Modes.cache”。
它可以使用绞合实用程序显示。这两个文件都来自glibc。
发布于 2016-11-25 18:16:15
原因是它需要对当前的地区做一个Unicode感知的比较,从Marat的回答来看,这样做的效率不高。
这表明,当没有考虑Unicode时,它的速度要快得多:
$ time LC_CTYPE=C grep -i fun test.txt
all work and no plJack is no fun
Jack is no Fun
real 0m0.192s当然,这种替代方法不能与其他语言的字符一起使用,例如: in / and、Of /、/and、/and/等。
另一种选择是修改regex,使其与大小写不敏感匹配:
$ time grep '[Ff][Uu][Nn]' test.txt
all work and no plJack is no fun
Jack is no Fun
real 0m0.193s这是相当快的,但当然,将每个字符转换为一个类是很痛苦的,并且不太容易将其转换为别名或sh脚本,这与上面的脚本不同。
比较而言,在我的系统中:
$ time grep fun test.txt
all work and no plJack is no fun
real 0m0.085s
$ time grep -i fun test.txt
all work and no plJack is no fun
Jack is no Fun
real 0m3.810shttps://stackoverflow.com/questions/13819635
复制相似问题