いつも忘れる正規表現の先読みと後読み(ルックアラウンドアサーション)のメモです。たぶん、ど忘れとかじゃなくて単にマスターできてないだけだと思います。
ルックアラウンドアサーションはパターンの周りを調べる「幅0のアサーション(zero-width assertion
)」です。幅0のアサーションは、それ自体が一つも文字を消費しない(幅がない)もので、文字列や行の始まりを表す(^
)や末尾の($
)、選択肢の(|
)とか、量指定子の(?, *, +
)とか、が該当します。詳しい解説はプログラミングPerlの「5章 正規表現」を読んでいただくといいかと思います。
肯定先読みアサーション (?=PATTERN)
positive lookahead
現在の文字列より先の部分(すぐ後ろ)にPATTERN
が現れていることを確認します。
my $str = 'あ い い い い い い い い う え お';
$str =~ s/b(.+)s(?=1)b//g;
print $str;
> あ い う え お
先読みアサーションを使用しない場合、ループで回す必要があります。先読みアサーションを使うと1片のコードで済みます。
my $str = 'あ い い い い い い い い う え お';
$str =~ s/b(.+)s1b/$1/g;
print $str;
> あ い い い い う え お
# ループで回す
$str =~ s/b(.+)s1b/$1/g while $str =~ /b(.+)s1b/;
否定先読みアサーション (?!PATTERN)
negative lookahead
現在の文字列より先の部分(すぐ後ろ)にPATTERN
が現れないことを確認します。
print "content-type: text/plain; charset=utf8\n\n";
my $str = '<p>Daryl Hall & John Oates</p>';
$str =~ s/&(?!amp;)/&/g;
print $str;
> <p>Daryl Hall & John Oates</p>
肯定後読みアサーション (?<=PATTERN)
positive lookbehind
現在の文字列より前の部分(直前)にPATTERN
が現れていることを確認します。
my $str = 'お父さん、お母さん';
$str =~ s/(?<=母)さん/様/g;
print $str;
お父さん、お母様
否定後読みアサーション (?<!PATTERN)
negative lookbehind
現在の文字列より前の部分(直前)にPATTERN
が現れてないことを確認します。
my $str = 'お父さん、お母さん、お兄さん、お姉さん';
$str =~ s/(?<!父)さん/様/g;
print $str;
お父さん、お母様、お兄様、お姉様