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

Hello folks, am new bee to perl and while writing a code i got stuck need some help. I want to search a bunch of strings which are stored in an array , and search those strings inside files of a specific directory. but am not able to do it , here is my code may be if u can help thanks in advance . . .
#!/usr/bin/perl my $file_name = $ARGV[0]; # parsing filename the elements of thi +s file will be sotred in @store array my $dir = $ARGV[1]; # parsing the directory in which the c +ontents of array will be searched in each file of this directory open (F, "$file_name") || die ("Could not open $file_name!"); # open +ing file while($line = <F>) { print "pushwala while"; push (@store, $line); #storing contents of file to @stor +e array } print "@store"; # printing contents of array close (F); # closing file opendir (DIR, $dir) or die $!; # opening directory , of which we ha +ve to precess all files my @dir = readdir DIR; foreach my $filename (@dir) { # print "$filename\n"; open (F, "$dir/$filename") || die ("Could not open $filename"); # o +pening Each file of the directory foreach (@store) { print "$_"; # printing contents of @store array , F +IXME here is the problem this prints 3 times all the contents of @sto +re array while($line = <F>) # cheking each line of files in th +e directory { print "$line"; # check if ($line =~ /$_/) # pattern matching between co +ntens of array and each line of files in directory { chomp ($_); #last if; print "testcase name:$_\n"; + # print "file includeing testcase:$filename\n"; + # if pattern is found printing it print "line:$line\n"; + # break; # breaking while loop } else { chomp ($_); print "$_:not found\n\n"; + # if pattern is not found break; # breaking while loop } } } }
# problem with this script is, i want to check all the lines of all the files included in the diretory and if the pattern is not found then only print that string not found, # but instead it is printing on every line string not found . and if the string is found i.e matched in a file the it should discontinue its search . Please help me folks

Replies are listed 'Best First'.
Re: Search strings stored in array into files of a directory
by Athanasius (Cardinal) on Jul 27, 2015 at 13:33 UTC

    Hello tejas1991, and welcome to the Monastery!

    In addition to the problems already identified by other monks, your script has some logic errors. First, this code (in outline):

    while (my $line = <F>) { if ($line =~ /$_/) { ... last; # breaking while loop } else { ... last; # breaking while loop } }

    makes no sense: whatever the outcome of the regex match, the loop is guaranteed to terminate after the first line. Second, and more importantly, this:

    open (F, "$dir/$filename") || die ("Could not open $filename"); foreach (@store) { ... while ($line = <F>) { ... } }

    cannot work, because once the inner while loop finishes on the first iteration of the outer foreach loop, the filehandle F no longer points to the first line of the file, so subsequent iterations of the foreach loop will never see the file’s first line(s). You could look at correcting this by resetting the filehandle using seek; but the code would still be inefficient. A better approach is to reverse the order of the loops:

    open(my $F, '<', "$dir/$filename) or die "Cannot open file '$dir/$file +name' for reading: $!"; OUTER: while (my $line = <$F>) { foreach my $string (@store) { if ($line =~ /\Q$string\E/) { ... next OUTER; } } } close $F or die "Cannot close file '$dir/$filename': $!";

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Search strings stored in array into files of a directory
by GotToBTru (Prior) on Jul 27, 2015 at 12:14 UTC

    I would add not to rely on $_ except in very limited contexts. Use an explicitly named variable. The value of $_ could change on you unexpectedly.

    Dum Spiro Spero
Re: Search strings stored in array into files of a directory
by toolic (Bishop) on Jul 27, 2015 at 11:20 UTC
Re: Search strings stored in array into files of a directory
by Nemo Clericus (Beadle) on Jul 27, 2015 at 12:55 UTC

    Welcome to the monastery. We strongly suggest you add the following to the top of your code...

    use strict; use warnings;

    Besides being just good form - it helps debugging immensely.

Re: Search strings stored in array into files of a directory
by pme (Monsignor) on Jul 27, 2015 at 13:25 UTC
    Why do you use perl? grep can do that for you:
    grep -f pattern.file directory/*
Re: Search strings stored in array into files of a directory
by 1nickt (Canon) on Jul 27, 2015 at 14:23 UTC

    Hi tejas1991 Another monk has already pointed out that you should have use strict; use warnings; at the top of your script. Here are another couple of suggestions.

    It's good to comment your code, but because you're using up to 8-space indentation, and then placing the comments at the end of the line, it makes the script hard to read. You should put the comments on the line above. It's also not usually necessary to comment a line that is very simple and clear. Get into the habit of writing clear, simple code that you can read, and save the comments for more confusing parts of your program. Also, I recommend 2-char indentation, but certainly no more than 4, and most importantly, be consistent!

    Use the three-argument form of open() and assign your filehandle to a non-global variable. See perlopentut.

    Mostly avoid using || as it can bite you if you forget the parentheses: prefer or. See Logical or and Exclusive Or.

    You don't need to double-quote a variable unless it needs to be interpolated when used. I.e., not when passing it to open(). See an old tutorial on this site.

    chomp() your lines as you read them to remove new-line characters that will mess you up later. (You do some of this later in the script). See chomp.

    It's good to learn how to work manually in Perl including things like listing files in a directory, but you should use basic modules for basic tasks. For example, your current script reads all the files in the directory including the special files . and .. which you probably don't want. Use File::Find or one of its friendlier friends such as File::Find::Rule instead and you'll save time and protect yourself from typos and other simple errors.

    If you want to get each element of an array, use for @array or foreach my $element ( @array ).

    OK coffee's ready, good luck, have a great Monday :-)

    The way forward always starts with a minimal test.
Re: Search strings stored in array into files of a directory
by soonix (Chancellor) on Jul 28, 2015 at 09:09 UTC
    and if the string is found i.e matched in a file the it should discontinue its search
    You want to say:
    • ignore the rest of the file for "the string"
    • ignore the rest of the file for all strings in @store
    • stop searching the other files, too
    Possibly you meant "report matches only once per line and string", but this isn't clear. If that's your goal, then you should consider pme's tip, or look at ack which incidentally is written in perl, too.

    If it's for the learning experience, it is also a good idea to state your goals as clearly as possible, and then describe the intended course of action in detail. If you did the latter good enough, you can derive a considerable part of your program's structure from that.