ネタ元→ 正規表現でn回目の出現にマッチってどうやるんだろう
にあまり深く考えずに
(?:pattern){N-1}(pattern) とか?
と返したわけだが、どう考えてもこれは「N個のパターンにマッチして、最後のパターンをキャプチャする」正規表現だ。ていうか
最後のパターンを後で参照したいだけならキャプチャ有り無しで分けずに(pattern){N} で十分だよ...
N個目のパターンにマッチする とはすなわちマッチ全体(Perlで言うと $&)がN個目のパターンになってなきゃいけないので、zero-width-look-behindを使って (?<=(?:pattern){N-1})pattern とするのが正解ですかね。
気をつけなければいけないのは、 Perlでの zero-width-look-behind はlook-behindするパターンにマッチする文字列の長さが確定していなければいけないこと。量指定子(*,+,? もしくは {n,m}) が含まれていてマッチする文字列の長さが確定できない場合は使えない。({n}は、固定の量指定子なので使える)
まとめると、
# 5個目のパターン(a5)を取り出したい
my $text = 'a1a2a3a4a5a6';
my $pat = qr/a\d/;
$\="\n";
print $1 if $text =~ m/(?:$pat){4}($pat)/; # $`='', $&='a1a2a3a4a5', $'='a6', $1='a5'
print $1 if $text =~ m/($pat){5}/; # ditto
print $& if $text =~ m/(?<=(?:$pat){4})$pat/; # $`='a1a2a3a4' $&='a5', $'='a6'
# ↓これは間違い
print $& if $text =~ m/(?<=$pat){4}$pat/; # $`='a1' $&='a2', $'='a3a4a5a6'
# 5個目のパターン(aa5)を取り出したい
$text = 'a1a2aa3a4aa5a6';
$pat = qr/aa?\d/;
print $1 if $text =~ m/($pat){5}/; # $`='', $&='a1a2aa3a4aa5', $'='a6', $1='aa5'
$text =~ m/(?<=(?:$pat){4})$pat/; # エラー




