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

I have the following code:
next if $string !~ /<b>(\w|\.+\.zip)<\/b>/; &do_something_with($1);
Unfortunately that does not match. If i modify like this (remove parens):
next if $string !~ /<b>\w|\.+\.zip<\/b>/; &do_something_with($1);
it matches, but $1 isn't available.

How can I get it to match and still provide me with $1?

Replies are listed 'Best First'.
Re: RegEx, $1, problem
by ikegami (Patriarch) on Oct 28, 2004 at 14:52 UTC

    Change \w|\.+ to (?:\w|\.)+. You're currently matching single letter filenames and filenames consiting of multiple '.' followed by 'zip' because the + binds very tightly.

    You do need to parens around what you you want in $1: /<b>((?:\w|\.)+\.zip)<\/b>/;

      This fixed it. Thanks.
•Re: RegEx, $1, problem
by merlyn (Sage) on Oct 28, 2004 at 14:48 UTC
    This should work better:
    next unless $string =~ /<b>(\w|\.+\.zip)<\/b>/; &do_something_with($1);
    You have to have a successful match to have a $1.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.


    update: Ahh, I thought your problem was in not having a $1 after a failed match, but you've later determined it was your regex. My advice applies, just to a different problem. {grin}
      Isn't that the same as as the OP? You negated the if to unless AND the =~ to !~ for a net change of nothing.
      Same problem. If i remove the paren's it matches fine. If i add them back in nothing gets matched. I removed the "&do_something_with($1);" and replaced it with:
      print "got here.\n";
      for the sake of testing. those parens seem to be screwing it up.

      Perl version is 5.8.1-RC3 (comes with macosx)
Re: RegEx, $1, problem
by borisz (Canon) on Oct 28, 2004 at 15:04 UTC
    You want:
    next unless $string =~ /<b>([\w\.]+\.zip)<\/b>/;
    Boris
Re: RegEx, $1, problem
by Happy-the-monk (Canon) on Oct 28, 2004 at 14:52 UTC

    next if ...

    Whenever your match is true,   next   jumps all the rest of your statements and returns to the next iteration of the loop.

    Think about whether you need the   next   statement at all. If you do, you'd probably go well with:

    if ( $string =~ /(<b>\w|\.+\.zip<\/b>)/ ) { &do_something_with($1); # first next; # next }

    Concerning what to match, best you tell us in English what exactly you do mean to match?
    Is the pipe character an alternation? Or a literal pipe character? (write "\|" then, see perlre)

    Cheers, Sören

    Update: corrected the typo ikegami pointed out.
      Your if will only work if !~ is changed to =~.