Using just one Perl substitute or matching regular expression statement , how can we modify below code:
I need to modify the value of $pattern<
There are quite a few regular expression features that you can use to enforce this type of positional limitation on a pattern match.
Counting matches using a code block within a regex.
The following uses a boundary condition to enforce position, and then simply counts the number of times that the pattern matches using a code block within the regex.
I wouldn't necessarily recommend this solution, but it does work for later versions of perl:
use strict;
use warnings;
use re 'eval';
my $pattern = qr{F1};
my $string = "F1234F12F1F1234F12F13";
my $count;
$string =~ /^(?:.{5})*$pattern(?{ $count++ })(*FAIL)/g;
print $count, "\n";
Outputs:
4
Enforcing position using a Conditional Expression and pos
This is similar to the first solution because it also relies on a code block:
my $count = () = $string =~ /(?(?{pos() % 5 != 0})(*SKIP)(*FAIL))$pattern/g;
Using a Positive Lookahead Assertion and boundary conditions.
The following technique uses \G
and boundary conditions to enforce position. The only trick to this is recognizing that we need to gobble the next group of 5 characters so we don't match twice.
my $count = () = $string =~ m{ \G (?: .{5} )*? (?= ($pattern) ) .{5} }xg;
Use Backtracking Control Verbs to intentionally parse the string 5 characters at a time.
The following looks for a match to our pattern, if it doesn't see it, skips the next 5 characters.
my $count = () = $string =~ m{
(?= ($pattern) ) .{5} # Match pattern and move 5 characters
|
.{5} (*SKIP)(*FAIL) # Or just skip 5 characters.
}xg;
Use Position Information after matching.
The simplest solution is just to match the pattern at all positions, and then use positional information to filter out the matches that we don't want:
my $count;
while ( $string =~ /$pattern/g ) {
$count++ if $-[0] % 5 == 0;
}
You can use the perl special variable @LAST_MATCH_START to get the output:
use strict;
use warnings;
my $pattern = "F1";
my $string = "F1234F12F1F1234F12F13";
my $count;
while ( $string =~ /$pattern/g ) {
$count++ if $-[0] % 5 == 0;
}
print $count;
4