替换数百万个正则表达式 (perl)
Substituting millions of regular expressions (perl)
我有一个包含超过一百万行文本的文本文件。在每一行上,都有一个需要用名称替换的字母数字代码。我曾尝试使用不同的 Perl 脚本来执行此操作,但每次脚本都会死掉,因为它们使用了太多内存。我是 Perl 的新手,所以我想我做错了什么,这让工作太复杂了?
到目前为止,我已经尝试过:
use strict;
use warnings;
my $filename = 'names.txt';
my $data = read_file($filename);
$data =~ s/88tx0p/Author1/g;
##and then there are 1,000,000+ other substitution regexes.
write_file($filename, $data);
exit;
sub read_file {
my ($filename) = @_;
open my $in, '<:encoding(UTF-8)', $filename or die "Could not open
'$filename' for reading $!";
local $/ = undef;
my $all = <$in>;
close $in;
return $all;
}
sub write_file {
my ($filename, $content) = @_;
open my $out, '>:encoding(UTF-8)', $filename or die "Could not open
'$filename' for writing $!";;
print $out $content;
close $out;
return;
}
但后来我意识到这个脚本试图将输出写入原始文件,我想这会占用更多内存?所以我尝试了以下方法:
use strict;
use utf8;
use warnings;
open(FILE, 'names.txt') || die "File not found";
my @lines = <FILE>;
close(FILE);
my @newlines;
foreach(@lines) {
$_ =~ s/88tx0p/Author1/g;
##and then there are approximately 1,000,000 other substitution regexes.
push(@newlines,$_);
}
open(FILE, '>names_edited.txt') || die "File not found";
;
print FILE @newlines;
close(FILE);
但是,这再次占用了太多内存。请问我可以在使用最少内存量的同时获得有关执行此操作的方法的帮助吗?谢谢大家
您的问题是您使用的是 foreach
循环。这需要您将所有行加载到内存中,这是问题的根源。
在 while 循环中尝试:
open ( my $file, '<', 'names.txt' ) or die $!;
open ( my $output, '>', 'names_edited.txt' ) or die $!;
select $output; #destination for print;
while ( <$file> ) { #reads one line at a time, sets $_
s/88tx0p/Author1/g; #acts on $_ by default
print; #defaults to printing $_ to the selected filehandle $output
}
这将逐行工作(就像您的初始代码一样)但一次只会读取一行,因此内存占用量会大大降低。
我有一个包含超过一百万行文本的文本文件。在每一行上,都有一个需要用名称替换的字母数字代码。我曾尝试使用不同的 Perl 脚本来执行此操作,但每次脚本都会死掉,因为它们使用了太多内存。我是 Perl 的新手,所以我想我做错了什么,这让工作太复杂了? 到目前为止,我已经尝试过:
use strict;
use warnings;
my $filename = 'names.txt';
my $data = read_file($filename);
$data =~ s/88tx0p/Author1/g;
##and then there are 1,000,000+ other substitution regexes.
write_file($filename, $data);
exit;
sub read_file {
my ($filename) = @_;
open my $in, '<:encoding(UTF-8)', $filename or die "Could not open
'$filename' for reading $!";
local $/ = undef;
my $all = <$in>;
close $in;
return $all;
}
sub write_file {
my ($filename, $content) = @_;
open my $out, '>:encoding(UTF-8)', $filename or die "Could not open
'$filename' for writing $!";;
print $out $content;
close $out;
return;
}
但后来我意识到这个脚本试图将输出写入原始文件,我想这会占用更多内存?所以我尝试了以下方法:
use strict;
use utf8;
use warnings;
open(FILE, 'names.txt') || die "File not found";
my @lines = <FILE>;
close(FILE);
my @newlines;
foreach(@lines) {
$_ =~ s/88tx0p/Author1/g;
##and then there are approximately 1,000,000 other substitution regexes.
push(@newlines,$_);
}
open(FILE, '>names_edited.txt') || die "File not found";
;
print FILE @newlines;
close(FILE);
但是,这再次占用了太多内存。请问我可以在使用最少内存量的同时获得有关执行此操作的方法的帮助吗?谢谢大家
您的问题是您使用的是 foreach
循环。这需要您将所有行加载到内存中,这是问题的根源。
在 while 循环中尝试:
open ( my $file, '<', 'names.txt' ) or die $!;
open ( my $output, '>', 'names_edited.txt' ) or die $!;
select $output; #destination for print;
while ( <$file> ) { #reads one line at a time, sets $_
s/88tx0p/Author1/g; #acts on $_ by default
print; #defaults to printing $_ to the selected filehandle $output
}
这将逐行工作(就像您的初始代码一样)但一次只会读取一行,因此内存占用量会大大降低。