Perl中没有与大文件匹配的正则表达式

时间:2014-05-01 15:50:24

标签: regex perl

我有以下简单的脚本:

my $filename = './log_file';
my $file; 
open(FILE, "$filename") or die "Cant open $filename\n"; 
local $/ = undef; 
$file = <FILE>; 
close(FILE); 
my $regexp = 'Something\n';
print "OK\n" if ($file =~ m{$regexp}msg); 

log_file的内容是:

Something
Nothing
Nothing
Nothing
Nothing
.
.
.

当log_file的大小为2GB时,脚本打印OK。 但是当它的大小是2.1GB或更多时,它打印不正常。 谁知道为什么?以及如何解决这个问题?我不想拆分文件,因为我的正则表达式是多行

2 个答案:

答案 0 :(得分:4)

将文件加载到变量中时,将整个文件读入内存。这可能会导致您的内存超过2GB(取决于系统资源)。另外,根据您的操作系统可能会遇到引擎下的大文件处理问题(特别是在32位系统上),在unix上结帐“man largefile”,这将以2GB开始。

考虑到大小,最好在循环中一次读取行或块,而不是啜饮整个事物。也许在阅读文件时使用滚动的2(或更多)行窗口来处理多行匹配。

答案 1 :(得分:1)

您的perl可能无法在启用USE_LARGE_FILES的情况下进行编译,这会将文件大小限制为2 gigs。您可以使用以下命令验证此操作,例如check:

$perl -V:uselargefiles
uselargefiles='define';

正如dethorpe已经建议的那样,无论如何,修改脚本以逐行处理,或者如果要跨多行测试,然后使用缓冲区,可能是明智的。

以下是如何使用5行缓冲区测试多行正则表达式的示例:

use strict;
use warnings;

my @buffer;

while (<DATA>) {
    push @buffer, $_;

    if (@buffer == 5 || eof) {
        my $buffer = join '', @buffer;
        while ($buffer =~ m{([a-z]+)\n(\d+)}g) {
            # Truncate buffer for match found
            @buffer = substr $buffer, pos $buffer;

            print "$1\n";
        }

        shift @buffer;
    }
}

__DATA__
1
2
3
4
5
6
7
abc
123
10
def
456 ghi
789
13
14
15
16

输出

abc
def
ghi