JavaScriptの正規表現の戻り読みはPerlのそれよりも表現力が高い ― 2018年12月29日 22時37分
ECMAScript 2018で正規表現の戻り読み(lookbehind)が追加されました。
/(?<=foo)bar/.test('foobar'); // => true
'foobar'.replace(/(?<=foo)bar/, 'baz'); // => 'foobaz
正規表現の戻り読みと言えばPerlでは1998年7月リリースのバージョン5.005からサポートしており、そこから20年もたってと思いたくなるかもしれません。しかし、ECMAScript (JavaScript)のそれはPerlのものとは一味違います。なんと戻り読みの中で量指定子(*
、+
、?
、{n}
など)を使えるのです。
// JavaScriptなら(?<=...)の中で+が使える。
/(?<=fo+)bar/.test('foobar'); // => true
# Perlでは(?<=...)の中で+を使おうとするとエラーになる。
"foobar" =~ m/(?<=fo+)bar/;
# => Variable length lookbehind not implemented in regex m/(?<=fo+)bar/ at - line 1.
Perlの場合、戻り読みとして指定されたパターンの文字数だけ戻ってから(文字列末尾方向に向けて)マッチしていきます。あらかじめ戻る文字数がわからないといけないので、戻り読みの中で量指定子を使えません。
一方、ECMAScriptでは戻り読みとして指定されたパターンそのものを逆方向に解釈し、1文字ずつ逆向きに(文字列先頭方向に向けて)マッチしていきます。ですから量指定子が含まれていても問題ないのです。
パターンが逆方向に解釈されるので、後方参照を使えるようになるのも戻る方向になります。
// 1番目の(...)よりも\1のほうが文字列先頭方向側にある。
// $& $1
/(?<=f\1(o))bar/.exec('foobar'); // => ["bar", "o"]
ただし、後方参照の番号はパターン内での出現順のままです。
// $& $1 $2
/([0-9]+)([0-9]+)兆円/.exec('5000兆円'); // => ["5000兆円", "500", "0" ]
/(?<=([0-9]+)([0-9]+))兆円/.exec('5000兆円'); // => ["兆円", "5", "000"]
最近のコメント