正規表現の先読みと後読みの使い方
はじめに
株式会社じげん の Web エンジニア、橋濱です!
正規表現にだんだん慣れてきたものの、含む・含まないでよく使う正規表現の「先読み」と「後読み」がいまいちで、いつもググりながら使ってます。
というわけで、もうググらなくても使えるようこの辺りを整理してみました。
どういう場合に使うか
先読み・後読みはどちらも、 特定の文字が前方(or 後方)に隣接している文字 をマッチさせるパターンです。
たとえば、文字列 hogefuga
は、
-
fuga
が前方(右側)に隣接しているhoge
であるし、 -
hoge
が後方(左側)に隣接しているfuga
ですね。
この前方か後方かという視点の違いで先読み・後読みという2種類のマッチパターンが用意されています。
先読み・後読みってどっちがどっち?
「先に読む、後に読む…って何それ?」という感じで、日本語訳をそのまま受け入れると個人的にめちゃくちゃ分かりづらいです。
「先」とか「後」とかいうのはもちろん隣接の前後関係を表しているのだと思いますが、なんかどちらで解釈しても成り立ちそうじゃないですか?
というわけで、元々の英語で理解を進めます。
- 先読みは lookahead(前方を見る、先を見る)
- 後読みは lookbehind(後方を見る、振り返る)
プログラミングは横書き文化なので、進行方向としては 左から右 をベースとしてイメージしてください。
- look ahead は、「隣接する・しないを確認したい文字」を起点(マッチさせたい文字)から 前方(右側)に見る
- look behind は、「隣接する・しないを確認したい文字」を起点(マッチさせたい文字)から 後方(左側)に見る
つまり、上で書いた例でいうと、文字列 hogefuga
について
- 「前方(右側)にある
fuga
が隣接する・しない」を見てhoge
をマッチさせようとしているのが lookahead(先読み) であるし、 - 「後方(左側)にある
hoge
が隣接する・しない」を見てfuga
をマッチさせようとしているのが lookbehind(後読み)
ということになります。
実際の使い方
ここまでが理解できればあとは簡単です!
肯定・否定の違いは文字どおり、隣接する・しないの違いでしかありません。
以下4種類、それぞれの記述と結果を見ていきましょう。
- 肯定先読み
- 否定先読み
- 肯定後読み
- 否定後読み
先読み
先読みは、特定の文字が前方(右側)に隣接している文字をマッチさせるパターンでしたね。
次の3行のテキストを検索対象とします。
imghoge
imgfuga
imgpiyo
肯定先読み
(?=)
という記法を使います。
たとえば「 hoge
を前方(右側)に隣接している img
をマッチさせたい」とします。
その場合、正規表現パターンは img(?=hoge)
となります。
imghoge # この行の img とマッチします
imgfuga
imgpiyo
否定先読み
(?!)
という記法です。
ビックリしてるわけじゃないので !?
と間違えないよう気をつけてください!
いつも ?
スタートです。
「 fuga
を前方(右側)に隣接して いない img
をマッチさせたい」とすると、正規表現パターンは img(?!fuga)
となります。
imghoge # この行の img とマッチします
imgfuga
imgpiyo # この行の img とマッチします
後読み
後読みは、特定の文字が後方(左側)に隣接している文字をマッチさせるパターンでしたね。
次の3行のテキストを検索対象とします。
hogebtn
fugabtn
piyobtn
肯定後読み
(?<=)
という記法です。
(?<=)
とするか (?>=)
かで迷うかもしれませんが、山括弧の向き的に、前者だと 後方(左側)を見てる感 がありますよね!
「 piyo
を後方(左側)に隣接している btn
をマッチさせたい」とすると、正規表現パターンは (?<=piyo)btn
となります。
hogebtn
fugabtn
piyobtn # この行の btn とマッチします
否定後読み
(?<!)
という記法です。
「 hoge
を後方(左側)に隣接して いない btn
をマッチさせたい」とすると、正規表現パターンは (?<!hoge)btn
となります。
hogebtn
fugabtn # この行の btn とマッチします
piyobtn # この行の btn とマッチします
まとめ
ユースケースとしては、特定の属性を含む HTML 要素周りの一括置換とかで使えそうですね!
「先読み」「後読み」という用語が、「前読み」「後ろ読み」とかだったら分かりやすかったのかもしれない…。
Discussion