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

Hey, Should be a simple one, but I can't seem to find the answer. I want to pattern match against a user-defined variable. eg:
#!/usr/bin/perl -w my $pattern = <STDIN>; open (FILE, "< filename"); while (<FILE>) { if (/$username/) { print "$_ \n"; } }
Of course, the $ in the $username matches and end-of-line character. How do I get round this?
toeslikefingers.com - because you've got too much time on your hands

Replies are listed 'Best First'.
Re: Pattern matching against a variable
by broquaint (Abbot) on Nov 04, 2003 at 11:11 UTC
    Just put $pattern in the match e.g
    ## remove regex-unfriendly newline chomp( my $pat = <STDIN> ); open(FILE, "filename") or die("ack: $!"); while(<FILE>) { print if /$pat/; }
    That will get a line of user input, loop over FILE and print if a given line matches $pat. Because regexes are interpolated the $ of $pat isn't interpreted as the meta-character $, but is interpolated into the regex match. See. perlop and perlre for more information on regexes and their quoting behaviour.
    HTH

    _________
    broquaint

      Ok, here's the *actual* code:
      open (LOGFILE, "/var/log/tac_acc.log"); while (<LOGFILE>) { print if /$username/; #if (/$username/) { #print "<br>",$_; # } }
      Apologies for leaving the comments in there, but you can see what I've done and what you've suggested. They both falsely match against *everything* though, and print the whole log file.. Is there something I'm missing?
      toeslikefingers.com - because you've got too much time on your hands
        Are you sure $username is defined and initialized? Turning on the likes of strict and warnings might help, as it looks like $username is empty/undefined and therefore creating an empty regex which matches everything.
        HTH

        _________
        broquaint

Re: Pattern matching against a variable
by ysth (Canon) on Nov 04, 2003 at 12:21 UTC
    Perl tries to guess whether $ is an end-of-line test or a variable to interpolate. It almost always guesses right; your problem is something different.

    By the way, if you do a match like /$usersuppliedpattern/, there are few things to be aware of:

  • if you want characters such as '*' to be treated literally, quotemeta the variable: /\Q$userpat/
  • if the pattern will never change, use the //o flag
  • or if the match is in a loop and the pattern isn't changed in it, set $userpat = qr/$userpat/ and match with =~ $userpat to avoid recompilation (assuming your perl version supports qr//).
  • if the var may be empty be aware that m/$emptyvar/ (or s/$emptyvar//) will not always succeed (as an empty regex should) but rather reuse the last successful pattern your program has matched (a particularly confusing kind of action at a distance only allowed for hysterical raisins). You can foil this with /(?:)$var/
Re: Pattern matching against a variable
by delirium (Chaplain) on Nov 04, 2003 at 12:31 UTC
    Not to belabor the obvious, but is $username set to anything? Print it out before the regexp loop to make sure. Nothing in the code you've shown us so far sets it.

    (Update - yeh, what Broquaint said... an hour ago.)