Perlの正規表現エンジンは可変長のルックビハインドをサポートしていないため、慎重に検討する必要があります。
sub runs_of_length {
my($n,$str) = @_;
my $n_minus_1 = $n - 1;
my $_run_pattern = qr/
(?:
# In the middle of the string, we have to force the
# run being matched to start on a new character.
# Otherwise, the regex engine will give a false positive
# by starting in the middle of a run.
(.) ((?!\1).) (\2{$n_minus_1}) (?!\2) |
#$1 $2 $3
# Don't forget about a potential run that starts at
# the front of the target string.
^(.) (\4{$n_minus_1}) (?!\4)
# $4 $5
)
/x;
my @runs;
while ($str =~ /$_run_pattern/g) {
push @runs, defined $4 ? "$4$5" : "$2$3";
}
@runs;
}
いくつかのテストケース:
my @tests = (
"xxaaaayyybbbbbzzccccxx",
"aaaayyybbbbbzzccccxx",
"xxaaaa",
"aaaa",
"",
);
$" = "][";
for (@tests) {
my @runs = runs_of_length 4, $_;
print qq<"$_":\n>,
" - [@runs]\n";
}
出力:
"xxaaaayyybbbbbzzccccxx":
-[aaaa] [cccc]
"aaaayyybbbbbzzccccxx":
-[aaaa] [cccc]
「xxaaaa」:
-[aaaa]
「aaaa」:
-[aaaa]
"":
-[]
これは楽しいパズルですが、正規表現を嫌う同僚は、そのような構造が本番コードに表示された場合、不幸になる可能性があります。