开发者

Nested while loop which does not seem to keep variables appropriately

I'm an amature Perl coder, and I'm having a lot of trouble figuring what is causing this particular issue. It seems as though it's a variable issue.

sub patch_check {
  my $pline;
  my $sline;
  while (<SYSTEMINFO>) {
    chomp($_);
    $sline = $_;

    while (<PATCHLIST>) {
      chomp($_);
      $pline = $_;
      print "sline $sline pline $pline underscoreline $_ "; #troubleshooting

      print "$sline - $pline\n";
      if ($pline =~ /($sline)/) {
        #print " - match $pline -\开发者_如何转开发n";
      }
    } #end while
  }
}

There is more code, but I don't think it is relevant. When I print $sline in the first loop it works fine, but not in the second loop. I tried making the variables global, but that did not work either.

The point of the subform is I want to open a file (patches) and see if it is in (systeminfo). I also tried reading the files into arrays and doing foreach loops.

Does anyone have another solution?


It looks like your actual goal here is to find lines which are in both files, correct? The normal (and much more efficient! - it only requires you to read in each file once, rather than reading all of one file for each line in the other) way to do this in Perl would be to read the lines from one file into a hash, then use hash lookups on each line in the other file to check for matches.

Untested (but so simple it should work) code:

sub patch_check {
  my %slines;
  while (<SYSTEMINFO>) {
    # Since we'll just be comparing one file's lines
    # against the other file's lines, there's no real
    # reason to chomp() them
    $slines{$_}++;
  }
  # %slines now has all lines from SYSTEMINFO as its
  # keys and the values are the number of times the
  # line appears, in case that's interesting to you

  while (<PATCHLIST>) {
    print "match: $_" if exists $slines{$_};
  }
}

Incidentally, if you're reading your data from SYSTEMINFO and PATCHLIST, then you're doing it the old-fashioned way. When you get a chance, read up on lexical filehandles and the three-argument form of open if you're not already familiar with them.


Your code is not entering the PATCHLIST while loop the 2nd time through the SYSTEMINFO while loop because you already read all the contents of PATCHLIST the first time through. You'd have to re-open the PATCHLIST filehandle to accomplish what you're trying to do.

That's a pretty inefficient way to see if the lines of one file match the lines of another file. Take a look at grep with the -f flag for another way.

grep -f PATCHFILE SYSTEMINFO


What I like to do in such cases is: read one file and create keys for a hash from the values you are looking for. And then read the second file and look if the keys are already existing. In this way you have to read each file only once.

Here is example code, untested:

sub patch_check {
    my %patches = ();

    open(my $PatchList, '<', "patch.txt") or die $!;
    open(my $SystemInfo, '<', "SystemInfo.txt") or die $!;

    while ( my $PatchRow = <$PatchList> ) {
        $patches($PatchRow) = 0;
    }

    while ( my $SystemRow = <$SystemInfo> ) {
        if exists $patches{$SystemRow} {
            #The Patch is in System Info
            #Do whateever you want
        }
    }
}


You can not read one file inside the read loop of another. Slurp one file in, then have one loop as a foreach line of the slurped file, the outer loop, the read loop.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜