Perl -逐行读取.txt文件并使用比较函数(只打印一次不匹配项)



我真的很挣扎,花了整整两天的时间在这上面,每次我运行这个perl脚本都收到相同的结果。

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

我还从目录中的.txt文件(逐行)中读取,并将文本文件中存在的服务器名称与$e->{'element4'}中存在的服务器名称进行比较。

问题:

匹配工作完美,当存在匹配时,仅为26个元素中的每个元素打印一行,而非匹配则为.txt文件中的每个条目生成一行(总共37行)。因此,如果有100个条目(每个条目有26个元素)存储在@data中,那么将打印100 x 37个条目。

对于:if ($e->{'element4'} eq '6' &&$_ =~/$e->{element7}/i)语句,我收到一个打印输出,说没有匹配。对于相同的26个元素有37个条目(因为在所有.txt文件中总共有37个条目)。

目标:

我只需要为每个唯一条目打印1行(唯一条目为$e->{element1}到$e->{element26})。对于匹配项,它已经打印了一行,但是当没有匹配项时,它打印了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)'

我想我需要一些东西来相同的唯一元素和定义什么字段构成一个唯一的元素,但老实说,我已经尝试了我所知道的一切。如果您能提供实际的代码修复,那就太好了,因为我很快就会使用这个脚本进行生产。也。我正在寻找代码(理想情况下),这是非常人类可读的,因为我需要记录它,以便其他人可以理解。

如果你需要更多的信息,请告诉我。

我个人会把所有坏节点推到一个数组中,然后用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;
    }
}

您正在测试某一行是否匹配'element 7',如果匹配-打印所有元素。如果it 不匹配,你似乎在做同样的事情?

你想在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";   
}
还是我错过了你想要完成的事情?

最新更新