Perl - Reading .txt files line-by-line and using compare function (printing non-matches only once)
Posted
by
Kurt W
on Stack Overflow
See other posts from Stack Overflow
or by Kurt W
Published on 2014-08-21T15:58:30Z
Indexed on
2014/08/21
16:20 UTC
Read the original article
Hit count: 168
I am really struggling and have spent about two full days on this banging my head against receiving the same result every time I run this perl script.
I have a Perl script that connects to a vendor tool and stores data for ~26 different elements within @data. There is a foreach loop for @data that breaks the 26 elements into $e->{'element1'), $e->{'element2'), $e->{'element3'), $e->{'element4'), etc. etc. etc.
I am also reading from the .txt files within a directory (line-by-line) and comparing the server names that exist within the text files with what exists in $e->{'element4'}.
The Problem:
Matches are working perfectly and only printing one line for each of the 26 elements when there is a match, however non-matches are producing one line for every entry within the .txt files (37 in all). So if there are 100 entries (each entry having 26 elements) stored within @data, then there are 100 x 37 entries being printed.
So for every non-match in the: if ($e->{'element4'} eq '6' && $_ =~ /$e->{element7}/i) statement below, I am receiving a print out saying that there is not a match. 37 entries for the same identical 26 elements (because there are 37 total entries in all of the .txt files).
The Goal:
I need to print out only 1 line for each unique entry (a unique entry being $e->{element1} thru $e->{element26}). It is already printing one 1 line for matches, but it is printing out 37 entries when there is not a match. I need to treat matches and non-matches differently.
Code:
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)'
I think I need something to identical unique elements and define what fields make up a unique element but honestly I have tried everything I know. If you would be so kind to provide actual code fixes, that would be wonderful because I am headed to production with this script quite soon. Also. I am looking for code (ideally) that is very human-readable because I will need to document it so others can understand.
Please let me know if you need additional information.
© Stack Overflow or respective owner