Perl - 逐行读取.txt文件并使用比较功能(仅打印非匹配一次)

时间:2014-08-21 15:58:30

标签: perl unique elements

我真的很挣扎,并且每次运行这个perl脚本时都会花费大约两整天的时间来反对接收相同的结果。

我有一个Perl脚本,它连接到供应商工具,并在 @data 中存储~26个不同元素的数据。 @data有一个foreach循环,将26个元素分解为$ e-> {' element1'),$ e-> {' element2'),$ e-&gt ; {' element3'),$ e-> {' element4')等等。

我也正在读取目录中的.txt文件(逐行),并将文本文件中存在的服务器名称与 $ e-> {'元素4'}

问题:

当匹配时,匹配工作完美且只为26个元素中的每个元素打印一行,但不匹配为.txt文件中的每个条目生成一行(37 in所有)。因此,如果@data中存储了100个条目(每个条目有26个元素),则会打印100 x 37个条目。

因此,对于以下各项不匹配:if($ e-> {' element4'} eq'&& $ _ =〜/ $ e- > {element7} / i)下面的声明,我收到的打印出来说没有匹配。相同的26个元素共有37个条目(因为所有.txt文件中共有37个条目)。

目标:

我需要为每个唯一条目打印出1行(唯一条目是$ e-> {element1}通过$ e-> {element26})。它已经为匹配打印了1行,但是当没有匹配时它打印出37个条目。我需要区别对待比赛和不比赛。

代码:

foreach my $e (@data) {
    # Open the .txt files stored within $basePath and use for comparison:
    opendir( DIRC, $basePath . "/" ) || die("cannot open directory");
    my @files = ( readdir(DIRC) );
    my @MPG_assets = grep( /(.*?).txt/, @files );

    # Loop through each system name found and compare it with the data in SC for a match:
    foreach (@MPG_assets) {
        $filename = $_;
        open( MPGFILES, $basePath . "/" . $filename ) || die "canot open the file";
        while (<MPGFILES>) {
            if ( $e->{'element4'} eq '6' && $_ =~ /$e->{'element7'}/i ) {
                ## THIS SECTION WORKS PERFECTLY AND ONLY PRINTS MATCHES WHERE $_
                ## (which contains the servernames (1 per line) in the .txt files)
                ## EQUALS $e->{'element7'}.
                print $e->{'element1'} . "\n";
                print $e->{'element2'} . "\n";
                print $e->{'element3'} . "\n";
                print $e->{'element4'} . "\n";
                print $e->{'element5'} . "\n";
                # ...
                print $e->{'element26'} . "\n";

            } else {
                ## **THIS SECTION DOES NOT WORK**.  FOR EVERY NON-MATCH, THERE IS A
                ## LINE PRINTED WITH 26 IDENTICAL ELEMENTS BECAUSE ITS LOOPING THRU
                ## THE 37 LINES IN THE *.TXT FILES.

                print $e->{'element1'} . "\n";
                print $e->{'element2'} . "\n";
                print $e->{'element3'} . "\n";
                print $e->{'element4'} . "\n";
                print $e->{'element5'} . "\n";
                # ...
                print $e->{'element26'} . "\n";
            }    # End of 'if ($e->{'element4'} eq..' statement
        }    # End of while loop
    }    # End of 'foreach(@MPG_assets)'
}    # End of 'foreach my $e (@data)'

我认为我需要相同的独特元素,并定义哪些字段构成一个独特的元素但老实说,我已经尝试了我所知道的一切。如果你真的很善于提供实际的代码修复,那将是非常好的,因为我很快就会使用这个脚本进行生产。也。我正在寻找非常人性化的代码(理想情况下)因为我需要记录它以便其他人可以理解。

如果您需要其他信息,请与我们联系。

2 个答案:

答案 0 :(得分:0)

我个人会将所有坏节点推送到一个数组并用List :: MoreUtils拉出我想要的东西。此外,结果的样本也可能有用。

# 1/2 Sudo Code
# =========================
use List::MoreUtils qw(uniq);

#...

else
{
    while ( $i <= 26 ) {
        push @nonMatches, $e->{'element$i++'};
    }

    my @badElements = uniq @nonMatches;
    foreach $element ( @badElements )
    {
        print $element;
    }
}

答案 1 :(得分:0)

您正在测试特定行是否与元素7&#39;匹配,如果匹配,则打印所有元素。而它没有匹配,你似乎在做同样的事情?

您在else代码块中尝试做什么?

我会猜测你可能想要尝试的是:

my %match_found_in;
my %match_found_of;
while(my $line = <MPGFILES>) {
    chomp $line;
    if ($e->{'element4'} eq '6' && $line =~ /$e->{'element7'}/i) { 
        $match_found_in{$filename} = $line; 
        $match_found_of{$e->{'element7'}} = $filename;
    }
}

foreach my $element ( keys %match_found_of ) {
  print "$element had a match in ".$match_found_of{$element},"\n";
}

foreach my $filename ( keys %match_found_in ) {
  print "$filename had a match on :", $match_found_in{$filename},"\n";   
}

或者我错过了你想要完成的事情?