根据多种模式快速过滤巨大的69GB文本文件的最佳方法

时间:2015-12-06 20:34:21

标签: python grep

过滤文件中与~20,000种组合之一匹配的行的最佳方法是什么?模式是\ tZZZZ \ t其中ZZZZ是我创建的列表中的数字。

我一直在使用:

for i in `cat patterns.txt`;
do
echo "$i
cat large_file.txt | LC_ALL=C grep $i >> matched_lines.txt 
done

但似乎很慢。 Python实现也非常慢......

大文件看起来像这样(制表符分隔,3列):

31599   94722   0.0184520931023
31599   33175   0.021944980284
31599   95587   0.0181413842575
31599   93637   0.0184741548464
31599   32411   0.0122635750533
31599   55509   0.0145808169111

2 个答案:

答案 0 :(得分:2)

使用GNU sed和bash:

sed -n -f <(sed -n 's|.*|/\t&\t/p|p' patternfile.txt) largefile.txt > result.txt

使用GNU sed,grep和bash:

grep -f <(sed -n 's|.*|\t&\t|p' patternfile.txt) largefile.txt > result.txt

答案 1 :(得分:0)

我也遇到了类似的挑战,我已经确定了数百万个模式,这些模式需要在具有数百万行的文件中进行匹配。在我的案例中,模式是字符串,用于标识搜索文件中所需的记录/行。

特征码文件为〜550万行特征码304MiB。
要搜索的文件是750万行json文档(每行一个json文档),25.1GiB。

因此,根据我的计算,此问题的循环迭代超过41万亿。

7,500,000 * 5,500,000 = 41,250,000,000,000.

我的逻辑是需要在750万行/记录的每一行中搜索550万次搜索。

patterns文件中的模式是唯一的。因此,我有一个想法,每次匹配一个模式,都可以从下一次搜索迭代中将其丢弃,从而减少迭代次数。我试图在python中实现一些东西,但是它太慢了,即使我以后要并行化它。

如果有人可以发表评论以理智地检查我的逻辑/数学,我将不胜感激。

这是我想出的解决方案:

fgrep -f是一个显而易见的选择,但是〜300 MiB / 5.5百万行的模式导致内核OOM杀手在程序中很早就终止了该过程。

因此,我利用GNU parallels工具按如下方式帮助对特征文件进行分块:

# create 7MB chunks (~100k lines/patterns per chunk), pass each chunk to fgrep -f
time parallel --tmpdir /dev/shm --pipepart --block 7m \
-a ../missing-eventIds-comm-quoted.txt --files 'cat' |
parallel --tmpdir /dev/shm -j4 -L1 --line-buffer '
  fgrep -f {} < <(exec 3<> /dev/pts/3; openssl enc -aes-256-cbc -d \
  -pass env:SYMETRIC_KEY -in possible-missing-data.gz.enc |
  gunzip --stdout | pv -s7510130 --line-mode 2>&3 -N job{#} )
  # remove the chunk
  rm {}
' | gzip --stdout |
openssl enc -aes-256-cbc -salt -pass env:SYMETRIC_KEY > $matches.gz.enc

--files的{​​{1}}选项将输入分块为文件,并在stdout上输出文件名。因此,在第二个parallel中,parallel模板令牌被替换为块文件名之一。请注意稍后的{}来清理大块。在此调用中,rm {}搜索搜索文件parallel次,直到处理完所有块为止。

根据我的数据,该方法以750万行文件的46个块迭代完成。我指定了n 4个并行作业,经过的时间约为23分钟。
节点正在使用-j4的{​​{1}} vCPU。

这种方法使Intel(R) Xeon(R) Gold 6242 CPU @ 2.80GHz的内存使用量保持名义。

澄清以下内容:

16 GB RAM

这是流程替换的示例,但是fgrep -f呢?我有一个< <(exec 3<> /dev/pts/3; openssl enc -aes-256-cbc -d \ -pass env:SYMETRIC_KEY -in possible-missing-data.gz.enc | gunzip --stdout | pv -s7510130 --line-mode 2>&3 -N job{#} ) exec 3<>上运行,我想监视读取搜索文件的进度。因此,我在文件描述符3 tty上打开了该tty。我利用/dev/pts/3pipe viewer)来监视exec 3<> /dev/pts/3会话中的进度。这为我提供了每个并行过程的进度条和速度检查。这是可选的。