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

Hi,
I' writing a code to get the files that match a string from directory
my code works fine to some extent
it couldnt match the whole string
for example - it matches admin/1.1 and admin but i need it to match only admin/1.1
I couldn't achieve it with ^ in front and $ at the back
please help me in this regard
Thanks in advance
Code is given below
my $str = "string to be matched"; opendir(TEMP,'/ade/nachekur_view2/oracle/work/hosts/brhost3/br/xcr')or + die "cannot open dude \n" ; my @FILES=readdir TEMP; my $fi = scalar (@FILES); for (my $k = 0; $k < $fi ; $k++) { open (F,$FILES[$k]) or die " rey ledhu ra \n"; my @lines = <F>; for (@lines) { if ($_ =~ m/$str/) { print "$_\n"; print "Lined that matched $str in $FILES[$k] \n"; last ; } } } closedir(TEMP); }

Replies are listed 'Best First'.
Re: Problem with regex
by johngg (Canon) on Sep 16, 2008 at 13:13 UTC
    A couple of points not related to your issue with the regex.

    • From a style and a code maintenance point of view, it might be better to move the closedir(TEMP); line up to immediately after the my @FILES=readdir(TEMP); line since you've done with reading the directory handle at that point.
    • It is now considered good practice to use the three-argument form of open with lexical filehandles and, when testing for success as you do (well done ++), it is useful to output the O/S error $! (see perlvar).
    • It is perhaps better to use Perl-style for loops rather than C-style ones. You can use for and foreach interchangeably. Instead of

      my $fi = scalar (@FILES); for (my $k = 0; $k < $fi ; $k++) { open (F,$FILES[$k]) or die " rey ledhu ra \n"; ... };

      use

      foreach my $file ( @FILES ) { open my $inFH, '<', $file or die "open: < $file: $!\n"; ... }
    I hope this is of interest.

    Cheers,

    JohnGG

      I would actually suggest forgoing the loop altogether and using grep:
      my @FILES = grep { -f } readdir (TEMP); foreach my $file (@FILES){ open (F, $file) or warn "Couldn't open $file: $!" and next; my @matches = grep { /$str/ } <F>; close (F); next unless scalar @matches > 0; print join("\n", @matches); }
      Of course, that prints every matching line in the file, if you only want the first (evidenced by "last"), you could just use:
      print $matches[0], "\n";
      And do you really want to use "die" in a loop? What if you can't open one file, but you can open the rest? Isn't "warn and next" more appropriate?
        I would actually suggest forgoing the loop altogether and using grep

        Nothing wrong with using grep to fill the @FILES array, although I might do grep { -f and not -l } depending on how symlinks should be treated. However, unless my eyes are failing me, you still have the loop in your code.

        And do you really want to use "die" in a loop?

        The OP seems to and, since I don't know what the requirements are, I followed his/her lead.

        Cheers,

        JohnGG

Re: Problem with regex
by svenXY (Deacon) on Sep 16, 2008 at 11:17 UTC
    Hi,
    and welcome to the monastery!

    I'm afraid I don't really understand your question. You talk about "admin" and "admin/1.1", but in your example code (++nave448 for providing it), the search string is "string to be matched". What are you actually looking for here?

    Regards,
    svenXY
      Hi,
      thanks for the reply
      "string to be matched" is the search string
      for example if i give it as admin/1.1 it gives me the file that contains the string admin/1.1
      But if i give it as admin it also gives me the same file
      I just want to match the whole word admin/1.1 not the part admin
      regards, Naveen
Re: Problem with regex
by llancet (Friar) on Sep 16, 2008 at 11:31 UTC
    The way you use regex is very unreliable. The regex system have some reserved characters, If your "string to be matched" has that kind of character, you will confuse the regex. You need to find a module that translates a string to a regex-compatiable search string, or you should translate the string manually.
      No need for a module, the quotemeta built-in function does that. You can also use \Q$searchstring\E in the regex (which does the same).
      Thanks. I got the problem
Re: Problem with regex
by Sagacity (Monk) on Sep 16, 2008 at 14:08 UTC

    Check out the perlre man page, which explains in good detail how to work with regex.

    When using characters that are normally interpreted as syntax, in your case (/ and .) these characters must be escaped. To have a slash (/) represent a slash literally, you designate the character to be escaped by adding a backslash in front of it like so (\/). This tells perl to interpret the slash / literally. The same is true of the period (\.) and other characters that are normally used as perl syntax.

    Hope this helps!