Python 如果一个非常大的文件不包含换行符,如何从中复制匹配项?

Python 如果一个非常大的文件不包含换行符,如何从中复制匹配项?,python,linux,bash,perl,grep,Python,Linux,Bash,Perl,Grep,问题是,我无法避免使用包含新行的超大文件: <a>text1</a>...gigabytes of data here, all in one single line...[a text to extract b> 它只会给出一个错误:内存耗尽(这是一个相关问题:)。 sed和awk都不允许使用这样的文件。那么,我应该如何从中提取匹配项呢 #!/usr/bin/perl use strict; use warnings; use constant BLOCK_

问题是,我无法避免使用包含新行的超大文件:

<a>text1</a>...gigabytes of data here, all in one single line...[a text to extract b>
它只会给出一个错误:内存耗尽(这是一个相关问题:)。
sed和awk都不允许使用这样的文件。那么,我应该如何从中提取匹配项呢

#!/usr/bin/perl

use strict;
use warnings;

use constant BLOCK_SIZE => 64*1024;

my $buf = "";
my $searching = 1;
while (1) {
   my $rv = read(\*STDIN, $buf, BLOCK_SIZE, length($buf));
   die($!) if !defined($rv);
   last if !$rv

   while (1) {
      if ($searching) {
         my $len = $buf =~ m{\[(?:a|\z)} ? $-[0] : length($buf);
         substr($buf, 0, $len, '');

         last if $buf !~ s{^\[a}{};

         $searching = 0;
      } else {
         my $len = $buf =~ m{b(?:>|\z)} ? $-[0] : length($buf);
         print substr($buf, 0, $len, '');

         last if $buf !~ s{^b>}{};

         print("\n");
         $searching = 1;
      }
   }
}
做出了很多假设:

  • 假定起始标记的拼写正确
    [a
  • 假定结束标记的拼写正确
    b>
  • 假设每个开始标记都有相应的结束标记
  • 假设每个结束标记都有相应的开始标记
  • 假设在
    [a
    b>
    之间找不到
    [a
Grep从2.21版开始:

搜索二进制数据时,grep现在可以将非文本字节视为行 终结者。这可以显著提高性能

现在发生的是,对于二进制数据,所有非文本字节 (包括换行符)被视为行终止符。如果要更改此 行为,您可以:

  • 使用
    --text
    。这将确保只有换行符是行终止符

  • 使用
    --null data
    。这将确保只有null字节是行终止符


您是否尝试过
tr'\0'\n'
我测试了
tr'\0'\n'path/to/output.txt
现在,它对输入没有任何影响。output.txt仍然保持不变。基于行的工具不起作用。您最好用Perl或Python编写一个脚本来处理该文件。我编辑了相应地,e标记:)但奇怪的是,我认为这是一种非常常见的操作(例如),但在网上搜索没有显示这种脚本的示例…1.如何在控制台中使用它(即,如何指定输入和输出文件的名称)?2.如果我想复制
\[a.*?b>
匹配项怎么办?我不是在问标记(我发布了
*?
作为一个非常基本的示例),我想复制基于正则表达式的匹配。我相应地编辑了示例。3.如果匹配大小超过32KB,会发生什么?我准备跳过这些匹配,但脚本会发生什么?1.
a.pl重复限制在这里不适用。大多数情况下(仅?)对于
{m,n}
。对不起,我不是一个Perl程序员。1.
是什么?3.我想,如果文件开头某处包含
[a
,结尾包含
b>
,会有一个大问题?内存不足!避免这种问题的唯一方法是在regex中指定一个限制,如
[a.{064000}b>
,对吗?1.重定向输入。您已经知道如何重定向输出。2.不,您可以假设
b>
即将出现,并在找到
[a
后立即开始打印。
#!/usr/bin/perl

use strict;
use warnings;

use constant BLOCK_SIZE => 64*1024;

my $buf = "";
my $searching = 1;
while (1) {
   my $rv = read(\*STDIN, $buf, BLOCK_SIZE, length($buf));
   die($!) if !defined($rv);
   last if !$rv

   while (1) {
      if ($searching) {
         my $len = $buf =~ m{\[(?:a|\z)} ? $-[0] : length($buf);
         substr($buf, 0, $len, '');

         last if $buf !~ s{^\[a}{};

         $searching = 0;
      } else {
         my $len = $buf =~ m{b(?:>|\z)} ? $-[0] : length($buf);
         print substr($buf, 0, $len, '');

         last if $buf !~ s{^b>}{};

         print("\n");
         $searching = 1;
      }
   }
}