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

2024-09-25 06:27:27 发布

您现在位置:Python中文网/ 问答频道 /正文

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

<a>text1</a>...gigabytes of data here, all in one single line...[a text to extract b>

如果我想从这个文件复制匹配项(为了方便起见,将每个匹配项放在单独的行中),我应该怎么做?比如说,<b>.*?</b>。你知道吗

如果我使用

grep -Pzo '\[a .*? b>' path/to/input.txt > path/to/output.txt

它只会给出一个错误:内存耗尽(这是一个相关的问题:grep-memory-exhausted)。
sed和awk都不允许处理这样的文件。那么,我应该如何从中提取匹配项呢?你知道吗


Tags: 文件oftopathintxtdatahere
2条回答

Grep从版本2.21开始有different behavior

When searching binary data, grep now may treat non-text bytes as line terminators. This can boost performance significantly.

所以现在的情况是,对于二进制数据,所有的非文本字节 (包括换行符)被视为行终止符。如果你想改变这个 行为,你可以:

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

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

line-regexp option with null data

#!/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>。你知道吗
  • 假设每个开始标记都有相应的结束标记。你知道吗
  • 假设每个结束标记都有相应的开始标记。你知道吗
  • 假设在[ab>之间找不到[a。你知道吗

相关问题 更多 >