Programming from 30

自分の備忘録が、誰かの為になれば・・

正規表現で注意すべき点!について

最近正規表現を学習中、初心者歓迎!手と目で覚える正規表現入門を元に学習し、少しずつ苦手意識が薄れてきました。
今回はこのサイトの最後の方に正規表現について注意すべき事

(_+|\w+)*a のように、+ や * が ( ) の中にも外にも出てくる正規表現は危険です。こういう正規表現は内部的な組み合わせの数が爆発的に増え、とんでもなく遅くなることが多い

と言及されていたので、少し調べてみました!

まずはこのような080-1234-5678電話番号のマッチングを例とし、比較する正規表現は以下の2点

①\d{3}-\d{4}-\d{4}
②.*-.*-.*

この2つの正規表現の処理の様子を見て行きたいと思います。 プログラム初心者の僕は、なるべくシンプルで簡潔である方(例の為、変な正規表現)が良いと思い②番を選んでいました。ただShin x Blogや多くの方が、正規表現は長い方が良いとおっしゃっています。 その理由をregular expressions 101で見てみます。
まずは①番 f:id:tsubasa0105:20181105183942p:plain 右上に6ステップとマッチし、これが過程です f:id:tsubasa0105:20181105184057p:plain こんな感じで正規表現を左から綺麗にマッチングされています。
次に②番 f:id:tsubasa0105:20181105184300p:plain 右上に27ステップと4倍以上の処理がかかっていて、過程がこちら f:id:tsubasa0105:20181105184453p:plain ちょっと飛ばします f:id:tsubasa0105:20181105184529p:plain

②は.*に差し掛かった時点で全てにマッチしてしまったが為に-でマッチするものがなくなってしまい、一個ずつ戻りながら、マッチングを繰り返します。このようなマッチング方法をバックトラッキングwiki と呼ぶようです。ちょっと効率悪く時間もその分かかってしまいます。
もし、もっと長い正規表現.*を多様していくと、ブログトップの引用のようにサーバーに高負荷がかかるのが容易に想像できます。
今回はわかりやすい②番のような変な正規表現で比較してしまいましたが、今後正規表現を使う際は、なるべく長く、マッチングがすぐにできるようなものを意識する必要がありますね!