在非常大的文件中快速搜索字符串

时间:2016-06-08 05:08:35

标签: linux bash grep

在包含字符串的文件中搜索行的最快方法是什么。我有一个包含要搜索的字符串的文件。这个小文件(smallF)包含大约50,000行,看起来像:

stringToSearch1
stringToSearch2
stringToSearch3

我必须在一个更大的文件中搜索所有这些字符串(大约 1亿行)。如果此较大文件中的任何行包含搜索字符串,则会打印该行。

到目前为止,我提出的最佳方法是

m/.+?(\d{4})<\/i>\)/s

但这不是很快。在smallF中只有100个搜索字符串,大约需要4分钟。对于超过50,000个搜索字符串,将花费大量时间。

有更有效的方法吗?

3 个答案:

答案 0 :(得分:16)

我曾经注意到使用-E或多个-e参数比使用-f更快。请注意,这可能不适用于您的问题,因为您在较大的文件中搜索50,000个字符串。但是,我想向您展示可以做什么以及可能值得测试的内容:

以下是我详细注意到的内容:

让1.2GB文件填充随机字符串。

>ls -has | grep string
1,2G strings.txt

>head strings.txt
Mfzd0sf7RA664UVrBHK44cSQpLRKT6J0
Uk218A8GKRdAVOZLIykVc0b2RH1ayfAy
BmuCCPJaQGhFTIutGpVG86tlanW8c9Pa
etrulbGONKT3pact1SHg2ipcCr7TZ9jc
.....

现在我想使用不同的grep方法搜索字符串“ab”,“cd”和“ef”:

  1. 使用不带标志的grep,一次搜索一个:

    grep“ab”strings.txt&gt; m1.out
    2,76s用户0,42s系统96%cpu 3,313总

    grep“cd”strings.txt&gt;&gt; m1.out
    2,82s用户0,36s系统95%cpu 3,322总计

    grep“ef”strings.txt&gt;&gt; m1.out
    2,78s用户0,36s系统94%cpu 3,360总计

  2. 所以总的来说搜索几乎 10秒

    1. 在search.txt

      中使用带有-f标记的grep和搜索字符串
      >cat search.txt
       ab
       cd
       ef
      
      >grep -F -f search.txt strings.txt > m2.out  
      31,55s user 0,60s system 99% cpu 32,343 total
      
    2. 由于某些原因,这几乎 32秒

      1. 现在使用-e

        的多种搜索模式
        grep -E "ab|cd|ef" strings.txt > m3.out  
        3,80s user 0,36s system 98% cpu 4,220 total
        

        grep --color=auto -e "ab" -e "cd" -e "ef" strings.txt > /dev/null  
        3,86s user 0,38s system 98% cpu 4,323 total
        
      2. 使用-E的第三种方法只需 4.22秒 来搜索文件。

        现在让我们检查一下结果是否相同:

        cat m1.out | sort | uniq > m1.sort  
        cat m3.out | sort | uniq > m3.sort
        diff m1.sort m3.sort
        #
        

        diff不产生输出,这意味着找到的结果是相同的。

        也许想尝试一下,否则我建议你看一下“最快可能的grep”这个帖子,看看Cyrus的评论。

答案 1 :(得分:1)

注意:我意识到以下内容不是基于bash的解决方案,但考虑到您的大型搜索空间,需要并行解决方案。

如果您的计算机多个核心/处理器,您可以在Pythran中调用以下函数,以并行化搜索:

#!/usr/bin/env python

#pythran export search_in_file(string, string)
def search_in_file(long_file_path, short_file_path):
    _long = open(long_file_path, "r")

    #omp parallel for schedule(guided)
    for _string in open(short_file_path, "r"):
        if _string in _long:
            print(_string)

if __name__ == "__main__":
    search_in_file("long_file_path", "short_file_path")

注意:在幕后,Pythran采用Python代码并尝试将其积极地编译成非常快速的C ++。

答案 2 :(得分:1)

您可以尝试siftag。筛选特别列出了一些非常令人印象深刻的基准与grep。