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

Bash My.gz/.zip文件包含一个巨大的文本文件;在不将文件解包保存到磁盘的情况下,如何提取与正则表达式匹配的行?,bash,shell,unix,command-line,awk,perl,Bash,Shell,Unix,Command Line,Awk,Perl,我有一个文件.gz(不是.tar.gz!)或文件.zip文件。它包含一个名为1.txt的文件(20GB大小的文本文件,包含数千万行) 在不将1.txt作为一个整体保存到磁盘的情况下(此要求与中相同),我希望提取与某个正则表达式匹配但与另一个正则表达式不匹配的所有行 生成的.txt文件不得超过预定义的限制,例如一百万行 也就是说,如果1.txt中有3.5M行符合这些条件,我想得到4个输出文件:part1.txt、part2.txt、part3.txt、part4.txt(后者将包含500K行),仅

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

  • 在不将
    1.txt
    作为一个整体保存到磁盘的情况下(此要求与中相同),我希望提取与某个正则表达式匹配但与另一个正则表达式不匹配的所有行
  • 生成的
    .txt
    文件不得超过预定义的限制,例如一百万行 也就是说,如果
    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可以做到,就像我的一样,但我不知道怎么做。

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

    如果您希望创建一个包含多个成员的归档文件,那么 成员以后可以独立提取,请使用archiver 比如柏油或者拉链

    更新:反编辑后,如果
    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
    也是一个不错的选择,但是你必须在它之后重命名文件。

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

    如果您希望创建一个包含多个成员的归档文件,那么 成员以后可以独立提取,请使用archiver 比如柏油或者拉链

    更新:反编辑后,如果
    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
    也是一个不错的选择,但您必须在它之后重命名文件。

    您的解决方案几乎不错。问题是您应该为
    gzip
    指定要执行的操作。要解压缩,请使用-d。因此,请尝试:

    gzip -dc path/to/test/file.gz | grep -P --regexp='my regex' | split -l1000000 
    
    但是有了这个,你会有一堆文件,比如xaa,xab,xac。。。我建议使用前缀和数字后缀功能来创建更好的输出:

    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
    

    我希望这能有所帮助。

    您的解决方案几乎不错。问题是您应该为
    gzip
    指定要执行的操作。要解压缩,请使用-d。因此,请尝试:

    gzip -dc path/to/test/file.gz | grep -P --regexp='my regex' | split -l1000000 
    
    但是有了这个,你会有一堆文件,比如xaa,xab,xac。。。我建议使用前缀和数字后缀功能来创建更好的输出:

    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
    是一个包装器脚本(与
    gzip
    package一起安装),它在内部使用与其他答案中提到的相同的命令。
    但是,它在脚本中看起来更可读&手动编写命令更容易。

    您可能可以使用

    注意:
    zgrep
    是一个包装器脚本(与
    gzip
    package一起安装),它在内部使用与其他答案中提到的相同的命令。


    但是,它在脚本中看起来更可读&手动编写命令更容易。

    grep是否允许筛选与第一个正则表达式匹配而与第二个正则表达式不匹配的行?您可以使用
    grep
    ,然后使用
    grep-v
    @lyricallywicked,甚至可以使用正则表达式支持的先行和后视缓冲区。“您可以使用grep,然后使用grep-v”-需要大量的额外时间,因为您不能在一个命令中执行类似于
    --regex=“first”&&&&&!“second”
    的操作,对吗?“您可以使用先行和后视缓冲区“-不久前,我尝试使用regex唯一的方法来过滤不包含内容的内容。我只记得那太慢了。请参阅grep是否允许筛选与第一个正则表达式匹配而与第二个正则表达式不匹配的行?您可以使用
    grep
    ,然后使用
    grep-v
    @lyricallywicked,甚至可以使用regex支持的先行和后置缓冲区。“您可以使用grep,然后使用grep-v”-需要大量的额外时间,因为您不能执行类似
    --regex=“first”&&&!“第二个”
    在一个命令中,对吗?“您可以使用“向前看”和“向后看”缓冲区”-不久前,我尝试使用regex唯一的方法来过滤不包含内容的内容。我只记得那太慢了。请参阅使用ERE而不是样式正则表达式的此解决方案可能存在的问题。它们有完全不同的语法,所以除了非常基本的模式外,我的正则表达式很可能无法工作。@TrueY好吧,没关系,awk正则表达式可以enough@TrueYERE远远不能改变基本模式。也许你认为sed默认支持BRE。@EdMorton:如果我不清楚,很抱歉!我的意思是ERE(由
    awk
    grep-E
    使用)使用了与RE(也由
    grep-P
    使用)非常不同的语法。但是简单的模式可以在这两个方面都起作用(比如:“我的模式”)。Op在Q中指定了
    -P
    ,因此我想强调的是,如果使用样式RE,可能会失败。问题可能在于此解决方案使用的是ERE而不是样式regex。它们有完全不同的语法,所以除了非常基本的模式外,我的正则表达式很可能无法工作。@TrueY好吧,没关系,awk正则表达式可以enough@TrueYERE远远不能改变基本模式。也许你认为sed默认支持BRE。@EdMorton:如果我不清楚,很抱歉!我的意思是ERE(由
    awk
    grep-E
    使用)使用了一种非常不同的语法