我的 .gz/.zip 文件包含一个巨大的文本文件;在不保存解压到磁盘的文件的情况下,如何提取与正则表达式匹配的行?

My .gz/.zip file contains a huge text file; without saving that file unpacked to disk, how to extract its lines that match a regular expression?

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

  1. 不将 1.txt 作为一个整体保存到磁盘(此要求与 中的要求相同),我想提取其所有与某个正则表达式匹配但不匹配另一个的行正则表达式。
  2. 生成的 .txt 文件不得超过预定义的限制,例如,一百万行。

也就是说,如果 1.txt 中有 350 万行符合这些条件,我想得到 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 可以做到,就像我的 一样,但我不知道怎么做。

恐怕这是不可能的,引用自gzip man:

If you wish to create a single archive file with multiple members so that members can later be extracted independently, use an archiver such as tar or zip.

更新:反编辑后,如果gz只包含一个文件,像awk这样的一步工具应该没问题:

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

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

你的解决方案差不多好了。问题是您应该为 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

希望对您有所帮助。

您或许可以使用 zgrep

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

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