はじめに
筆者が運営するサイト『正規表現パズル』で扱っている、正規表現の問題とその答えを、EmEditorの正規表現を使って解説していきます。EmEditorの正規表現の文法は、『EmEditor 使い方: 正規表現構文』を参照してください(Perl準拠です)。
対象読者
『詳説 正規表現 第3版』を教科書として、本稿は問題集という位置づけとなりますので、『詳説 正規表現 第3版』を一読された方。
必要な環境
EmEditor Professional Version 6.00.4で動作確認しました。その他、プログラム言語やSQLやテキストエディタなどでも応用できます。
1. 複数の指定文字列を含む行の検索
まずは、複数の指定文字列を含む行を検索する正規表現についてです。
文字列abを含んで、かつ、 文字列bcを含んで、かつ、 文字列cdを含む行を検索する。
対象データと期待する検索結果は、下記となります(黄緑色が検索にヒットした部分です)。
単純に個々の条件を組み合わせると、3の階乗である3*2=6通りの順列に対応する正規表現をつないだ、次のようなパターンが考えられます。
^.*ab.*bc.*cd.*$| ^.*ab.*cd.*bc.*$| ^.*bc.*ab.*cd.*$| ^.*bc.*cd.*ab.*$| ^.*cd.*ab.*bc.*$| ^.*cd.*bc.*ab.*$
しかし、このパターンは5行目にはマッチしますが、1行目と7行目にマッチしないので、間違いです。文字列abと文字列bcに、bという共通文字があるのが、この問題のポイントです。
答えは、肯定先読みを使用して下記となります。
^(?=.*ab)(?=.*bc)(?=.*cd).*$
肯定先読みは、指定したパターンが先に存在する位置にマッチします。たとえば、(?=yz)
は次にyzがある位置にマッチしますので、検索対象が
xyz
であれば、文字xと文字yの間の位置にマッチします。
^(?=.*ab)(?=.*bc)(?=.*cd).*$
のように、肯定先読みを連続して使っている場合は、行頭にマッチして、その後.*ab
がある位置にマッチして、その後.*bc
がある位置にマッチして、その後.*cd
がある位置にマッチして、その後.*$
にマッチすると考えてもいいですが、行頭、かつ.*ab
がある、かつ.*bc
がある、かつ.*cd
がある位置からの.*$
にマッチすると考えた方が分かりやすいでしょう。言いかえると、肯定先読みを連続して使うとそれらの論理積が真となる位置にマッチするということです。
正規表現のイメージは、下記となります。