Kentdn has asked for the wisdom of the Perl Monks concerning the following question:

Hi I am new to perl and with the aid of this site completed a script to search file A find specific variables then seach file B for the pattern produced. Now this is all well and good except in my second foreach loop it loops once then stops. I am so close but yet so far from completing it. Can anybody suggest why the second foreach loop doesn't work as the rest seems to work fine. Please ingnore the "print..." they are there purily for debugging pruposes. Thanks for everybodies help in adavnce
print "Enter File name and path of .ins?"; $filename1 = <STDIN>; print "Enter the name of the .rcs file to be searched?"; $filename2 = <STDIN>; open( FILE, "< $filename1" ) or die( "can't find file1: $ +!" ); $/=undef; @file = <FILE>; close(FILE); print @file,\n; foreach $line (@file) { $line =~ /.*EditorName\b.*\b(.+?)\b/; $word1 = $1;} foreach $line2 (@file) { $line2 =~ /.*EditorCommand\s+'(\w+)'\s/; @word2 = $1;} print @word2, \n; open FILE, ">test54.txt" or die "Could not open file: $!\n"; open (Output, ">test54.txt"); foreach $word2 (@word2) { { $pattern = $word1.":".$word2; if (in_file($pattern, $filename2) ) { + print Output "Found $pattern in $filename2\n"; } else { print "$pattern not found in $filename2.\n"; } sub in_file { my ($pattern, $filename2) = @_; open FILE, $filename2 or die "Can't open $filename: $!\n +"; my $found =0; while (<FILE>) { $found=1, last if /$pattern/; } close FILE; $found; } } }

Replies are listed 'Best First'.
Re: help needed on a foreach loop from hell!!!
by VSarkiss (Monsignor) on Jan 24, 2002 at 05:52 UTC

    You've got a bit of a mish-mosh. I think you're trying to read in the entire file into memory, in @file, judging from this: @file = <FILE>; However, when you combine that with $/=undef, you get one long string from the <FILE>, which gets put in the first element of the array. TheDamian once gave an excellent description of what $/ does: "it tells Perl where to stop reading".

    Two common idioms are:

    1. undef $/; $var = <FILE>;
    2. This reads the whole file into the scalar variable $var.
    3. @array = <FILE>;This reads the entire file into @array, one line per element (where "line" is again defined by the contents of $/).
    Select one or the other technique; combing both gives strange effects, as you've found.

    In the preceding node, Ineffectual has noted some strange things as well. The one I find most perplexing is that you're sub definition is in the middle of a loop. Also, it looks like the error message your die prints after not being able to open the file came from a monastery copy-and-paste: it's got a + in the middle of the $!.

    HTH

      Thanks for everybodies help the suggestions have been great and I have learnt a lot from them; everybodies input has been greatly appreciated!!!
Re: help needed on a foreach loop from hell!!!
by Ineffectual (Scribe) on Jan 24, 2002 at 05:10 UTC
    Which foreach isn't working? The foreach $line2 (@file) or the foreach $word2 (@word2)? I did a few tests on my own, but without knowing what data you're searching through with the EditorCommand part, I'm not sure if it's your assignment of word2 into the array or if it's something further down. Correct assignment of an array usually utilizes push ie:  push(@word2, $1). The next thing to do is to print @word2 and $pattern to see if they're being assigned. Also, I'm not sure why your sub is in the middle of your code rather than at the bottom or why the $found is at the bottom of the script. It might help to post a snippet of the files that you're trying to parse.
    'Fect
    YMMV
      Thanks for your suggestions and the part that isn't working is the "foreach $line2". I think what is going wrong is that the code is overwriting the first position in the array, so I guess the question is how to I increment the scalar so it writes to a new position in the array? Also thanks for the general perl comments, I am really new to this and am trying to learn as much as I can as fast as I can; all the comments are a big help!
        Hopefully this isn't offensive, but personally I'd rewrite your code as:
        print "Enter file name and path of .ins to parse:\n"; my $filename1 = <STDIN>; die "File $filename1 does not exist\n" unless (-e $filename1); print "Enter file name and path of .rcs to search:\n";<br> my $filename2 = <STDIN>; die "File $filename2 does not exist\n" unless (-e $filename2); open (FILE, "<$filename1) or die "Can't open file $filename1 :$!\n"; my @file = <FILE>; close FILE; foreach my $line (@file) {
        Depending on what you're parsing here, I'd probably use a split rather than $1. YMMV.
        ie: If file line was "EditorName Susan Hammel" I'd do
        if ($line =~ /EditorName/) { my @name = split(/\s+/, $line); my $first = $name[1]; my $last = $name[2]; } foreach my $line2 (@file) { if ($line2 =~ /EditorCommand/) { my @commands = split(/s+/, $line2); shift @commands; # To remove the EditorCommand - Requires line that +looks like "EditorCommand print paste copy" } open (OUTPUT, ">>test.txt"); foreach my $com (@dcommands) { my $pattern = $word1 . ":" . $com; my $test = in_file($pattern, $filename2); if ($test) { print OUTPUT "Found $pattern in $filename2 \n"; } else { print "$pattern not in $filename2 \n"; } } exit; #### SUBS #### sub in_file { my $pattern = shift; my $filename2 = shift; open INFILE, $filename2 or die "Can't open $filename2: $!\n"; my $found = 0; while (<INFILE>) { if (/$pattern/) { $found = 1; last; } close FILE; return $found; }
        HTH, YMMV
        'Fect

        You'd indeed be correct about "@word2=$1" overwritting the first position of @word2. To whit, at assigns @word2 to the list consisting of the single element $1. As Ineffectual noted, the best way to do what you want here is generaly with a push, push @word2, $1; in this case. (BTW, following that push link will get you the same thing (more or less, depending on what version of perl you've got installed) as "perldoc -f push" from a command prompt. (If you're running ActiveState perl for win32, there's also a perlfunc.html sitting around that has the same thing in html form.)

        If you don't have it yet, BTW, I highly recommend "Programming Perl", AKA The Camel Book. Your library /should/ have it.

        TACCTGTTTGAGTGTAACAATCATTCGCTCGGTGTATCCATCTTTG ACACAATGAATCTTTGACTCGAACAATCGTTCGGTCGCTCCGACGC