$s = "bla..bla";
$s =~ s/([^%])\./$1/g;
I think it should replace all occurrences of .
that is not after %
with the character that is before .
.
But $s
is then: bla.bla
, but
it should be blabla
. Where is the problem? I know I can use quantifiers, but I need do it this way.
When a global regular expression is searching a string it will not find overlapping matches.
The first match in your string will be a.
, which is replaced with a
. When the regex engine resumes searching it starts at the next .
so it sees .bla
as the rest of the string, and your regex requires a character to match before the .
so it cannot match again.
Instead, use a negative lookbehind to perform the assertion that the previous character is not %
:
$s =~ s/(?<!%)\.//g;
Note that if you use a positive lookbehind like (?<=[^%])
, you will not replace the .
if it is the first character in the string.
The problem is that even with the /g
flag, each substitution starts looking where the previous one left off. You're trying to replace a.
with a
and then a.
with a
, but the second replacement doesn't happen because the a
has already been "swallowed" by the previous replacement.
One fix is to use a zero-width lookbehind assertion:
$s =~ s/(?<=[^%])\.//g;
which will remove any .
that is not the first character in the string, and that is not preceded by %
.
But you might actually want this:
$s =~ s/(?<!%)\.//g;
which will remove any .
that is not preceded by %
, even if it is the first character in the string.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With