Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl-逐行读取.txt文件并使用比较函数(仅打印一次非匹配项)_Perl_Unique_Elements - Fatal编程技术网

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

Perl-逐行读取.txt文件并使用比较函数(仅打印一次非匹配项),perl,unique,elements,Perl,Unique,Elements,我真的很挣扎,为此我花了整整两天的时间,每次运行这个perl脚本时都会收到相同的结果 我有一个Perl脚本,它连接到一个供应商工具,并在@data中存储约26个不同元素的数据。@data有一个foreach循环,它将26个元素分解为$e->{'element1')、$e->{'element2')、$e->{'element3')、$e->{'element4')等 我还读取目录中的.txt文件(逐行),并将文本文件中存在的服务器名称与$e->{'element4'}中存在的服务器名称进行比较

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

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

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

问题:

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)'
匹配工作正常,当存在匹配项时,只为26个元素中的每一个打印一行,但是非匹配项为.txt文件中的每个条目生成一行(总共37个)。因此,如果有100个条目(每个条目有26个元素)存储在@data中,然后打印100 x 37个条目

因此,对于下面的:if($e->{'element4'}eq'6'&&&$\u=~/$e->{element7}/i)语句中的每一个不匹配项,我都会收到一个打印输出,表示相同的26个元素没有匹配的.37个条目(因为在所有.txt文件中总共有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)'
我只需要为每个唯一条目打印一行(唯一条目是$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)'
foreach my$e(@data){
#打开存储在$basePath中的.txt文件并用于比较:
opendir(DIRC,$basePath.“/”)| | die(“无法打开目录”);
my@files=(readdir(DIRC));
my@MPG_assets=grep(/(.*).txt/,@files);
#循环查找找到的每个系统名称,并将其与SC中的数据进行比较以获得匹配:
foreach(@MPG_资产){
$filename=$\ux;
打开(MPGFILES,$basePath./“$filename)| | die“canot open the file”;
而(){
如果($e->{'element4'}eq'6'&&&$\u=~/$e->{'element7'}/i){
##此部分功能完美,仅打印匹配的内容$_
##(其中包含.txt文件中的服务器名(每行1个)
##等于$e->{'element7'}。
打印$e->{'element1'}.\n”;
打印$e->{'element2'}.\n”;
打印$e->{'element3'}.\n”;
打印$e->{'element4'}.\n”;
打印$e->{'element5'}.\n”;
# ...
打印$e->{'element26'}.\n”;
}否则{
##**此部分无效**。对于每个不匹配项,都有一个
##用26个相同元素打印的线条,因为其循环通过
##*.TXT文件中的37行。
打印$e->{'element1'}.\n”;
打印$e->{'element2'}.\n”;
打印$e->{'element3'}.\n”;
打印$e->{'element4'}.\n”;
打印$e->{'element5'}.\n”;
# ...
打印$e->{'element26'}.\n”;
}#if($e->{'element4'}eq..语句结尾
}#while循环结束
}#“foreach(@MPG_资产)”结尾
}#“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;
    }
}
#1/2 Sudo代码
# =========================
使用列表::MoreUtils qw(uniq);
#...
其他的
{
而($i{'element$i++');
}
my@badElements=uniq@nonMatches;
foreach$element(@badeelements)
{
打印$element;
}
}

您正在测试某一行是否与“element 7”匹配,如果匹配,则打印所有元素。如果不匹配,您似乎在做相同的事情

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";   
}
my%match\u在中找到;
我的%match\u find\u of;
while(我的$line=){
chomp$行;
如果($e->{'element4'}eq'6'&&$line=~/$e->{'element7'}/i){
$match_found_在{$filename}=$line中;
$match_found_of{$e->{'element7'}}=$filename;
}
}
foreach my$元素(键%match\u found\u of){
打印“$element在“{$element}”的“$match”中找到匹配项,“\n”;
}
foreach my$filename(在中找到%match\项){
打印“$filename在:”,在{$filename},“\n”中找到$match_;
}

或者我错过了您想要完成的任务?

匹配项通过一个工具发送到我们的自动化软件进行进一步处理。匹配项应该包括一个名为$e->{'groupType'}的新元素,它包含找到匹配项的文件名(哪个.txt文件).NON-MATCHES也应该使用相同的元素发送,除了$e->{'groupType'}元素应静态设置为“标准”。我使用打印语句只是为了对捕获的数据进行采样。我现在将尝试您的建议。最终目标是为@data中存储的100个条目中的每一个打印一行。这是