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

Linux 在非常大的文件中快速搜索字符串,linux,bash,grep,Linux,Bash,Grep,在包含字符串的文件中搜索行的最快方法是什么。我有一个包含字符串的文件要搜索。这个小文件(smallF)包含大约50000行,看起来像: stringToSearch1 stringToSearch2 stringToSearch3 我必须在一个更大的文件中搜索所有这些字符串(大约1亿行)。如果此较大文件中的任何一行包含搜索字符串,则打印该行 到目前为止,我想出的最好的方法是 grep -F -f smallF largeF 但这并不是很快。smallF中只有100个搜索字符串,大约需要4分钟。

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

stringToSearch1
stringToSearch2
stringToSearch3

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

到目前为止,我想出的最好的方法是

grep -F -f smallF largeF
但这并不是很快。smallF中只有100个搜索字符串,大约需要4分钟。对于超过50000个搜索字符串,这将需要很多时间


有没有更有效的方法?

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

以下是我注意到的细节:

使用随机字符串填充1.2GB文件

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

>head strings.txt
Mfzd0sf7RA664UVrBHK44cSQpLRKT6J0
Uk218A8GKRdAVOZLIykVc0b2RH1ayfAy
BmuCCPJaQGhFTIutGpVG86tlanW8c9Pa
etrulbGONKT3pact1SHg2ipcCr7TZ9jc
.....
现在我想使用不同的grep方法搜索字符串“ab”、“cd”和“ef”:

  • 使用不带标志的grep,一次搜索一个:
  • 因此,搜索总共需要将近10秒的时间

  • 在search.txt中使用带有搜索字符串的grep和
    -f
    标志

     >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
    
  • 出于某些原因,这几乎需要32秒

  • 现在使用带有
    -e

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

  • 使用
    -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的评论。

    注意:我意识到以下内容不是基于
    bash
    的解决方案,但鉴于您的搜索空间大,并行解决方案是有保证的


    如果您的机器有多个内核/处理器,您可以在中调用以下函数来并行搜索:

    #!/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++。

    < P>你可能想尝试或。Sift特别列出了一些与grep相比令人印象深刻的基准测试。

    No。这是最有效的方法,除非你可以并行搜索,或者编写一个特殊用途的程序。请参阅:
    fgrep
    而不是
    grep-F
    应该快一点…@Jahid:来自GNU grep的主页:“fgrep与grep-F相同。”@Jahid要澄清这是
    /usr/bin/fgrep
    的内容/bin/sh exec grep-F“$@”
    cat m1.out | sort | uniq > m1.sort  
    cat m3.out | sort | uniq > m3.sort
    diff m1.sort m3.sort
    #
    
    #!/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")