Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Using array elements for a file search

by Jeri (Scribe)
on Oct 24, 2011 at 19:37 UTC ( #933467=perlquestion: print w/replies, xml ) Need Help??
Jeri has asked for the wisdom of the Perl Monks concerning the following question:

Hi Perl Monks! I'm trying to use array elements in a file search. This is what I've written thus far. I want the script to be able to go through each array element and then search for that particular element in a file. My logic (to me) seems right, but I feel that I'm missing a fundamental concept.

This is the infile.

#INFILE A B C D

This is the code.

#!usr/bin/perl5.8.8 use strict; use warnings; my @array = qw (A B C D); open (my $INFILE,"<", "letters"); open (my $OUTFILE,">", "capturedletters"); my $Letter; foreach my $i (@array) { print "Foreach loop$i, "; print "\n"; while (<$INFILE>) { print "While loop$i, "; #this variable does not change if ($_ =~/^$i/) { print $OUTFILE "$_"; } } } close ($INFILE); close ($OUTFILE);

This is the output I get.

Foreach loopA, While loopA, While loopA, While loopA, While loopA, Foreach loopB, Foreach loopC, Foreach loopD,
Thanks!

Replies are listed 'Best First'.
Re: Using array elements for a file search
by jwkrahn (Monsignor) on Oct 24, 2011 at 20:04 UTC

    Your problem is that when the filehandle $INFILE reaches the end-of-file it will always return undef so after the first time through the foreach loop the while loop will never run,    You have to either open the file inside the foreach loop or put the foreach loop inside the while loop.

Re: Using array elements for a file search
by onelesd (Pilgrim) on Oct 24, 2011 at 20:07 UTC

    Code review aside, your example is interesting because you seem to be trying to capture every line of your input file and write it to another file (which can be done in a simpler way than this).

    The output to STDOUT looks like it does because you read $INFILE to the end when you checked for the letter "A", so the next time you try to while <$INFILE> {...} for letter "B" the pointer is already at EOF and the while <$INFILE> {...} isn't entered.

Re: Using array elements for a file search
by mrstlee (Beadle) on Oct 25, 2011 at 11:44 UTC
    I know they are scary at first but this is the kind of thing regular expressions were born for.

    The sample code below contains some comments which may help.
    use warnings; my @array = qw (A B C D); ## This example uses the open-file-handle-as-string feature ## Substitute \(my ...) for filepath open (my $INFILE,"<", \(my $in = join "\n", qw(aA d DDD CDA e XYZ AABB +CC))); open (my $OUTFILE,">", \(my $out)); ## Create a regular expression for all elements in the array. ## With the contents of array above the string created will be ## A+|B+|C+|D+ ## Note how the '+' is suffixed on at the end because the 'join' inser +ts ## between array elements. my $composite_elements_re = join ('+|',@array) . '+'; ## Turn the string into a real regex with qr. ## The 'x' modifier means you can add comments between the '/'s ## See perlretut etc in the perl documentation my $complete_re = qr/ $composite_elements_re /x ; while (my $rec = <$INFILE>){ ## The g modifier means get all matches. my @matches = $rec =~ /($complete_re)/gx ; ## If there are any matches print them to the output string (via f +ilehandle!) ## Note that '@matches and' forces @matches to be interpreted as a + scalar (single) value. ## An array treated as a scalar returns the number of elements. ## So long as @matches >= 1 the matches will be put in the output. @matches and do { print $OUTFILE @matches }; } close ($INFILE); close ($OUTFILE); ## Change to print to file of your choice - or leave as stdout? print "$out\n"; ## prints ADDDCDAAABBCC
      Hi, I'm looking for something very similar. I have an array of strings, which I want to match to the end of log file entries. At first I did something similar to the original poster:
      my @zones = `cat zones.txt`; chomp (@zones); open (IN, 'logfile.log'); while (<IN>) { chomp; foreach my $zone (@zones) { if ($_ =~ /$zone$/) { print "$zone match\n"; last; } } } close IN;
      But obviously that's rather inefficient and takes for ever. Could your example, of joining the array to a regular expression string, be modified and used in this case where it needs to match the end of the string?
Re: Using array elements for a file search
by Anonymous Monk on Oct 24, 2011 at 23:59 UTC

    Hi,

    I would put the data into a hash rather than an array, then you would only need one loop.

    J.C.

      I would but I'm the array I'm using is about to go right into List::Compare.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://933467]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (5)
As of 2018-08-20 14:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Asked to put a square peg in a round hole, I would:









    Results (191 votes). Check out past polls.

    Notices?