我的.gz / .zip文件包含一个巨大的文本文件;如果不将该文件解压缩到磁盘,如何提取与正则表达式匹配的行?

时间:2015-01-08 07:16:47

标签: bash shell unix command-line awk

我有 file.gz (不是 .tar.gz !)或 file.zip 文件。它包含一个名为1.txt的文件(带有数千万行的20GB大小的文本文件)。

  1. 不将1.txt整体保存到磁盘(此要求与my previous question中的相同),我想提取与正则表达式匹配的所有行,并且不匹配另一个正则表达式。
  2. 生成的.txt文件不得超过预定义的限制,例如一百万行。
  3. 也就是说,如果1.txt中有3.5M行匹配这些条件,我想得到4个输出文件:part1.txt,part2.txt,part3.txt,part4.txt(后者将包含500K行),就是这样。

    我试图使用像

    这样的东西
    gzip -c path/to/test/file.gz | grep -P --regexp='my regex' | split -l1000000 
    

    但上面的代码不起作用。也许Bash可以做到,就像在previous question中一样,但我不知道如何。

3 个答案:

答案 0 :(得分:3)

您可以使用zgrep

zgrep [ grep_options ] [ -e ] pattern filename.gz ...

注意:zgrep是一个包装脚本(与gzip软件包一起安装),它基本上在内部使用与其他答案中提到的相同的命令。
但是,它在脚本中看起来更具可读性。更容易手动编写命令。

答案 1 :(得分:2)

我害怕它是不可能的,引自gzip男人:

  

如果您希望创建包含多个成员的单个存档文件   以后可以单独提取成员,使用归档程序   如焦油或拉链。

更新:在编辑之后,如果gz只包含一个文件,那么像awk这样的一步工具就可以了:

gzip -cd path/to/test/file.gz | awk 'BEGIN{global=1}/my regex/{count+=1;print $0 >"part"global".txt";if (count==1000000){count=0;global+=1}}'

split也是一个不错的选择,但您必须在其后重命名文件。

答案 2 :(得分:1)

你的解决方案几乎是好的。问题是你应该为gzip指定做什么。要解压缩使用-d。所以试试:

gzip -dc path/to/test/file.gz | grep -P --regexp='my regex' | split -l1000000 

但是有了这个你会有一堆像xaa,xab,xac这样的文件......我建议使用PREFIX和数字后缀功能来创建更好的输出:

gzip -dc path/to/test/file.gz | grep -P --regexp='my regex' | split -dl1000000 - file

在这种情况下,结果文件将如下所示:file01,file02,fil03等。

如果你想过滤掉一些不匹配的样式正则表达式,你可以尝试这样的事情:

gzip -dc path/to/test/file.gz | grep -P 'my regex' | grep -vP 'other regex' | split -dl1000000 - file

我希望这会有所帮助。