正規表現の「または」or句について
**「|」(パイプ)**は、「どちらかにマッチ」だと思うけど、順番があるので注意。
普通の IF 文などの論理演算の OR と同じだと早合点してしまうと、順番なんかどうでもいいや、と思いがちだけど、正規表現の場合は、順番も重要になるので、注意。
例えば、
「ababc」という文字列をターゲットにする
これに対して、以下の正規表現を考える
「(([a-b])|(abc))+」
意味は、『a~bまでの文字、または「abc」という文字列』 が、1文字以上の領域。
マッチ文字列は、「abab」
最後の「c」がマッチしない。
一方、順番を逆にした以下の正規表現を考えると、
「((abc)|([a-b]))+」
マッチ文字列は、「ababc」
と最後の「c」も含まれる。
つまり、「(([a-b])|(abc))+」の正規表現の処理としては、
先頭の1文字目は「a」で[a-c]の表現にマッチ、2文字目も[a-c]でマッチ、3文字目も[a-c]でマッチ、4文字目も[a-c]でマッチ、5文字目は「c」なので、[a-b]ではマッチしないので、次の表現「abc」に遷移するもののマッチしない(「c」という表現では「abc」とマッチしない)。
マッチしなかった時に、n文字までマッチしていたものをn-1文字(n-m文字)に戻ってマッチしなおす。という事はしない。
一方、「((abc)|([a-b]))+」の場合は、
先頭の1文字目は「a」は「abc」でひとまず仮マッチするので、続けて1+1=2文字目は「b」なので、さらに継続して、1+2=3文字目は「a」なのでマッチしないので、1文字目からの「aba」は「abc」にマッチしないという事で、1文字に戻って、次の表現「a-b」でマッチ。2文字目も[a-b]でマッチ。3文字目は「a」なので、最初の表現「abc」にひとまず仮マッチで、次の文字、その次の文字とあわせて「abc」なので、完全にマッチ。・・・という事で、マッチした文字列は「ababc」となる。
...という流れを考えてみると分かりやすいかもしれない。