对一个大文件grep一个大列表

我目前正在尝试grep一个更大的csv文件(3.000.000行)的ID列表(〜5000)。

我想要所有的csv行,包含id文件中的一个id。

我天真的做法是:

 cat the_ids.txt | while read line do cat huge.csv | grep $line >> output_file done 

但是这需要永远!

有更有效的方法来解决这个问题吗?

尝试

 grep -f the_ids.txt huge.csv 

此外,由于你的模式似乎是固定的字符串,提供-F选项可能会加速grep

  -F, --fixed-strings Interpret PATTERN as a list of fixed strings, separated by newlines, any of which is to be matched. (-F is specified by POSIX.) 

为此使用grep -f

 grep -f the_ids.txt huge.csv > output_file 

man grep

-f文件, – 文件=文件

从FILE获取模式,每行一个。 空文件包含零模式,因此不匹配任何内容。 (-f由POSIX指定)。

如果你提供一些示例输入,也许我们甚至可以改善grep条件多一点。

测试

 $ cat ids 11 23 55 $ cat huge.csv hello this is 11 but nothing else here and here 23 bye $ grep -f ids huge.csv hello this is 11 but and here 23 

grep -f得到更大的文件不守规矩。 即使使用grep -f ,我们也需要记住一些事情:

  • 如果需要匹配第二个文件中的整行,请使用-x选项
  • 如果第一个文件有字符串,而不是模式,则使用-F
  • 使用-w来防止部分匹配,而不使用-x选项

这篇文章对这个主题进行了很好的讨论( grep -f在大文件上):

  • 从Bash中另一个更大的文本文件中找到文本文件的行的最快方法

这篇文章谈到了grep -vf

  • grep -vf对于大文件太慢了

总之,在大文件上处理grep -f的最好方法是:

匹配整行:

 awk 'FNR==NR {hash[$0]; next} $0 in hash' filter.txt data.txt > matching.txt 

匹配第二个文件中的特定字段(在本例中使用','分隔符和字段2):

 awk -F, 'FNR==NR {hash[$1]; next} $2 in hash' filter.txt data.txt > matching.txt 

grep -vf

匹配整行:

 awk 'FNR==NR {hash[$0]; next} !($0 in hash)' filter.txt data.txt > not_matching.txt 

匹配第二个文件中的特定字段(在本例中使用','分隔符和字段2):

 awk -F, 'FNR==NR {hash[$0]; next} !($2 in hash)' filter.txt data.txt > not_matching.txt