正規表現のおさらい (3)

正規表現のおさらいシリーズ
その1:http://developer.venture-net.co.jp/entry/2018/06/22/174206
その2:http://developer.venture-net.co.jp/entry/2018/06/29/192116
その4:http://developer.venture-net.co.jp/entry/2018/07/13/185653

前々回前回正規表現についておさらいしてきました。
今回は最長マッチと最短マッチについておさらいします。

最長マッチ

繰り返しを表現するものとして、?、*、+ がありました。* や + は0/1回以上 の繰り返しにマッチするわけですが、それでは a+ という正規表現は、文字列 "aaaab" のどこにマッチするのでしょうか。
これは aaaa にマッチします。デフォルトでは、可能な限り長くマッチするように動作します。このことを指して、最長マッチ とか 最長一致 と言ったりします。

最短マッチ

最長マッチの逆で、マッチ可能の部分で最も短いところにマッチする指定を 最短マッチ といい、* や + の後ろに ? をつけることで最短マッチになります。
a+? という正規表現は、文字列 "aaaab" の最初の a にマッチします。



上記の通り * や + はデフォルトでは最長マッチなのですが、それでは少し困る場合があります。例えばHTMLコードでaタグを探したいとします。

aタグは、 <a href="/">HOME</a> のように 開始タグ、テキスト、終了タグ からなり、開始タグにはいくつかの name="value" 形式の属性を指定することができます。

単純に考えると、これを抜き出すための正規表現はこのようになります。

<a .+</a>

つまり、
・<a が来て
・そのあとに空白が1つ来て
・そのあとに任意の文字が1つ以上来て
・最後に </a> という終了タグが来る
ということになります。
属性やリンクテキストがどのような文字で構成されるかはわかりませんから、.+ を使ってどのような文字にもマッチさせる試みは正しいように思われます。

しかしこれには落とし穴があります。

<a href="/">HOME</a> <a href="/access">ACCESS</a> <a href="/contact">CONTACT</a> とaタグが3つ並んでいる文字列の場合はどこにマッチするでしょうか。
この場合は、頭の <a から最後の </a> までの全体にマッチしてしまいます。 普通はこのようにマッチさせたいことはなく、それぞれのaタグにマッチさせたいはずです。

なぜこのようになるのかといえば、.+ が </a> にもマッチしてしまうからです。.+ は任意の文字が1回以上ですから、</a> にマッチするのは誤りではありません。 そしてデフォルトでは最長マッチのため、可能な限り長く -- 一番最後の </a> の手前までマッチしてしまうというわけです。

ここで最小マッチが活きます。 <a .+?</a> という正規表現であれば、マッチ可能な最小の長さでマッチするため、狙い通りの <a href="/">HOME</a> にマッチすることになります。