What I'm trying to do seems deceptively simple, but I can't find a way to make it work.
I want to match a number, capture it, and then match the following N characters in the string. Naively, I thought something like this would work:
$myString = "1abc3cdf\n";
# Capture the number, and use a back-reference in the {} to define how many characters to match
$myString =~ s/(\d+).{\1}//g;
print $myString;
I expect to get bc, but it just returns the original string 1abc3cdf, ie no substitution has taken place.
I tried with an extended regex (ie s///ge) but that didn't help. Any suggestions?
You may use the (??{...}) inline code block:
$myString =~ s/(\d+)(??{ ".{$^N}" })//g;
See the Perl demo.
Here is some reference:
This is a "postponed" regular subexpression. It behaves in exactly the same way as a
(?{ code })code block as described above, except that its return value, rather than being assigned to$^R, is treated as a pattern, compiled if it's a string (or used as-is if its a qr// object), then matched as if it were inserted instead of this construct.During the matching of this sub-pattern, it has its own set of captures which are valid during the sub-match, but are discarded once control returns to the main pattern.
And here is more about the whole regex:
(\d+) - Capturing group #1 that matches any one or more digits(??{ ".{$^N}" }) - a code block that represents "a "postponed" regular subexpression" whose return value is "treated as a pattern, compiled if it's a string". The "$^N contains whatever was matched by the most-recently closed group (submatch)" (see the perlre reference). In other words, if (\d+) captures 45, the (??{ ".{$^N}" }) turns into .{45} and thus matches any 45 characters other than line break characters.