我目前正在循环浏览一个日志文件,提取某些特征。我必须检查一个唯一的字符串是否重复,如果字符串重复,则忽略该日志。目前,我的代码需要花费大量的时间来运行(或者我处于无限循环中)yippey。有没有更好的方法从文件中提取重复项并检查其唯一性?
close($handle);
$test = "testFile.txt";
open( $handle, '<', $domainAnalysis ) or die "Cannot open file: $!";
open( $hand, '>', $test ) or die "Cannot open file: $!";
my %uniq;
while ( $search = <$handle> ) {
if ( $search =~ /Mail ID: ([^:]*)n/g ) {
$uniq{$search}++;
}
my @sortedHash = sort keys %uniq;
foreach $i (@sortedHash) {
if ( $i eq $search ) {
print $hand $search;
print $hand scalar <$handle> for 1 .. 2;
}
}
}
如有任何帮助,我们将不胜感激。我有点被卡住了。
编辑:
它目前正在读取一个日志文件,并将所需信息拉到一个新文件中。新文件以该的格式打印
Mail ID: b12342534
Domain : someEmail@email.com
Status Message = Sent
Mail ID: a32432234
Domain : someEmail@email.com
Status Message = Deferred
输出:程序实际上从未停止。这需要很长时间,我的耐心不会让它一直持续下去。
我很确定你的问题是内部循环——当你迭代日志时,可能会积累大量的"邮件ID"条目。
在每个循环中,对它们进行排序,然后对它们进行迭代并进行比较。
更重要的是,你在每个散列中插入的$search
是each LINE,这意味着它将变得巨大。
不管怎样,我建议考虑到你的输入数据,首先你使用$/
:
local $/ = ''; #read in paragraph mode.
my %seen;
while ( <$input> ) {
my ( $id ) = m/Mail ID: ([^:]*)/;
print unless $seen{$id}++;
}
这将只在第一次发现特定的邮件ID时打印。
(当然,如果您只想打印重复项,您可以使用"if"而不是"除非")
首先,不需要迭代哈希的所有键;它打破了散列的全部要点
假设你想要数组@arr
的元素$arr[3]
,你会写这个吗?
for my $i ( 0 .. $#arr ) {
if ( $i == 3 ) {
print "Found: $arr[$i]n";
}
}
因此您可以使用$uniq{$search}
访问%uniq
的任何先前存在的元素
其次,当您递增时,您可以简单地测试%uniq
的元素当前是否为零
像这个
my $test = 'testFile.txt';
my $domainAnalysis = '...';
open my $handle, '<', $domainAnalysis or die qq{Cannot open "$domainAnalysis": $!};
open my $hand, '>', $test or die qq{Cannot open "$test": $!};
my %uniq;
while ( my $search = <$handle> ) {
next unless $search =~ /^Mail ID:/;
if ( $uniq{$search}++ ) {
print $hand $search;
print $hand scalar <$handle> for 1 .. 2;
}
}
您还必须始终use strict
和use warnings 'all'
,并使用my
声明所有变量,使其尽可能接近首次使用的位置
对于文件句柄来说,$hand
和$handle
是可怕的名称!