in reply to s/// with an empty pattern uses the previous pattern of a s///

Yes, this is documented in perlop:

If the PATTERN evaluates to the empty string, the last successfully matched regular expression is used instead. In this case, only the g and c flags on the empty pattern is honoured - the other flags are taken from the original pattern. If no match has previously succeeded, this will (silently) act instead as a genuine empty pattern (which will always match).

If you want to $pat = ''; /$pat/ to match only empty strings, then add $pat = qr/^\z/ if not length($pat);
If you want to $pat = ''; /$pat/ to match everything, then add $pat = qr/.*/ if not length($pat);

Replies are listed 'Best First'.
Re^2: s/// with an empty pattern uses the previous pattern of a s///
by ikegami (Patriarch) on May 17, 2007 at 15:59 UTC

    Oh! Another to fix the problem is to add a no-op to the regexp.

    $\ = "\n"; $pat = 'b'; $_='abc'; s/$pat/!/g; print; $pat = ''; $_='abc'; s/$pat/@/g; print; $pat = ''; $_='abc'; s/(?:$pat)/#/g; print;

    outputs

    a!c a@c #a#b#c#

      Thank you for these tips. I'm not looking to replace the empty scalar, I'm looking to replace whatever is in that scalar with the value of a different scalar. Those values are determined dynamically so the best answer is to use, as you suggested, something like:

      $pat && ($msg =~ s/$pat/$replace/mg);

      I was doing some more searching and discovered this exact quote in the perlop man page, as you said in reply #1, however in my copy of the man page it is listed in the m// operator rather than the substitute operator I wasn't aware that it applied there also. It does make sense that it would do, but I have to note this to try to scrape together a little dignity after having just posted a question on something in the man pages like a newbie coder :)

      Thanks again for your help! Colin

        That won't work if $pat is zero. Fix:

        length($pat) && ($msg =~ s/$pat/$replace/mg);

        I have to note this to try to scrape together a little dignity after having just posted a question on something in the man pages like a newbie coder :)

        It's not well known, and it's easy to forget, because it's not a situation that's usually encountered. No dignity lost.

        By the way compiling the pattern is not enough. I ran a test that showed $pat = qr//; /$pat/ is the same thing as m// even though the stringification of $pat is not an empty string.

        I think even many old-timers rarely see this bug. You may want to change your expression to something like length( $path ) && ($msg =~ s/$pat/$replace/mg); because the expression 0 is false but non-empty and potentially meaningful to you.

        ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

        I'm looking to replace whatever is in that scalar with the value of a different scalar.

        Maybe I'm being dense, but why not just

        $msg =~ s/.*/$replace/s;
        A word spoken in Mind will reach its own level, in the objective world, by its own weight