Contents
正規表現でのAND条件は (?= )肯定先読み
正規表現でAND条件を指定する際には「^(?=.*AAA)(?=.*BBB).*$」
のように表現が必要です。OR条件の場合には「(AAA|BBB)」を踏まえて調整すればOKですが、AND条件にはひと工夫を求められます。
説明が長くなるため先に例を示しましょう。
(AAAを含む) AND (BBB含む)
(AAAを含む) AND (BBB含む)のような形にしたい場合には、「^(?=.*AAA)(?=.*BBB).*$」
とします。意味としては、AAAとBBBが文字列ないのどこかに含まれている場合にマッチする、となります。
// 正規表現で(ピカチュウを含む) AND (ヤドラン含む)
^(?=.*ピカチュウ)(?=.*ヤドラン).*$
// 検索対象
ピカチュウ カイリュー ヤドラン ピジョン
コダック コラッタ ズバット ギャロップ ピカチュウ
// 検索結果
ピカチュウ カイリュー ヤドラン ピジョン
(AAAを含む) AND (BBB含まない)
(AAAを含む) AND (BBB含まない)のような形にしたい場合には、「^(?=.*AAA)(?!.*BBB).*$」
とします。意味としては、AAAを含みBBBは含まない文字列にマッチする、となります。
// 正規表現で(ピカチュウを含む) AND (ヤドラン含まない)
^(?=.*ピカチュウ)(?!.*ヤドラン).*$
// 検索対象
ピカチュウ カイリュー ヤドラン ピジョン
コダック コラッタ ズバット ギャロップ ピカチュウ
// 検索結果
コダック コラッタ ズバット ギャロップ ピカチュウ
AND条件の仕組みを解説
ANDを解説するにあたっては、肯定先読みと否定先読みは避けて通れないので、先に確認しておきましょう。
肯定先読みと否定先読みとは
肯定先読みとは、特定のパターンにマッチした場合にその先(前)にアンカーを設置する書き方です。「(?=XXX)」のようにかき、XXXが検索対象にあった場合に「(?=XXX)」の前の位置にマッチします。
否定先読みとは、特定のパターンにマッチしなかった場合にその先(前)にアンカーを設置する書き方です。「(?!XXX)」のようにかき、XXXが検索対象になかった場合に「(?!XXX)」の前の位置にマッチします。
肯定先読みと否定先読みを詳しく解説するとそれだけで記事1本かけてしまうので、詳しくは次の記事をみてください。
上記を前提にいくつかの段階を踏みながら、AND条件の成り立ちをみていきましょう。
1.「^.*$」
まずは「^.*$」ですがこれらの記号はそれぞれ次のような意味となります。
これらを組み合わせると、何かしらの文字列が含まれるものすべてにマッチします。
// 正規表現で0文字以上の任意の文字列にマッチ(つまりなんでもOK)
^.*$
// 検索対象
ピカチュウ カイリュー ヤドラン ピジョン
コダック コラッタ ズバット ギャロップ ピカチュウ
// 検索結果
ピカチュウ カイリュー ヤドラン ピジョン
コダック コラッタ ズバット ギャロップ ピカチュウ
2.「^(?=AAA).*$」
次は「(?=AAA)
」を条件として追加します。肯定先読みを使うことでAAAが文頭にある文字列へマッチします。
// 正規表現でピカチュウではじまる文字列にマッチ
^(?=ピカチュウ).*$
// 検索対象
ピカチュウ カイリュー ヤドラン ピジョン
コダック コラッタ ズバット ギャロップ ピカチュウ
// 検索結果
ピカチュウ カイリュー ヤドラン ピジョン
上記の例では「^」のあとに「(?=ピカチュウ)」があるので、文頭にピカチュウの文字列を含まれている場合の文字列がヒットするようになります。そのうえで1で解説した「.*$」が続くため、ピカチュウから始まる何かしらの文字列を意味することになります。
3.「^(?=.*AAA).*$」
今度は2と違い「(?=AAA)
」が「(?=.*AAA)
」となり()内にも「.*
」が追加されています。これにより、先頭に限定していたAAAの文字列が、先頭以外でもどこからしらに含まれていればOKとなりました。
「(?=.*AAA)
」は「.*」によって、何かしらの文字列0文字以上(つまり何でもOK)のあとにAAAが続くことを指定しています。そのため「^(行頭)」→「.*(何でもOK)」→「AAA」となり、AAAが文字列内のどこかに含まれていればマッチするようになります。
// 正規表現でピカチュウではじまる文字列にマッチ
^(?=.*ピカチュウ).*$
// 検索対象
ピカチュウ カイリュー ヤドラン ピジョン
コダック コラッタ ズバット ギャロップ ピカチュウ
// 検索結果
ピカチュウ カイリュー ヤドラン ピジョン
4.「^(?=.*AAA)(?=.*BBB)
.*$」
(?=.*BBB)
.*$」「^(?=.*AAA)
では(?=.*BBB)
.*$」「
の肯定先読みをさらに追加することで、AAAもBBBも含まれている場合にマッチします。ここの肯定先読みは文字列内に含まれているかを意味しているので(?=.*BBB)
」「^(?=.*BBB)
のように順番を入れ替えても意味は同じです。(?=.*AAA)
.*$」
// 正規表現でピカチュウではじまる文字列にマッチ
^(?=.*ピカチュウ)(?=.*ヤドラン).*$
// 検索対象
ピカチュウ カイリュー ヤドラン ピジョン
コダック コラッタ ズバット ギャロップ ピカチュウ
// 検索結果
ピカチュウ カイリュー ヤドラン ピジョン
コダック コラッタ ズバット ギャロップ ピカチュウ
5.「^(?=.*AAA)(?!.*BBB)
.*$」
(?!.*BBB)
.*$」
の肯定先読みを「(?!.*BBB)」として否定先読みにすれば、含まない場合にマッチする表現が可能です。「(?=.*BBB)」
// 正規表現で(ピカチュウを含む) AND (ヤドラン含まない)
^(?=.*ピカチュウ)(?!.*ヤドラン).*$
// 検索対象
ピカチュウ カイリュー ヤドラン ピジョン
コダック コラッタ ズバット ギャロップ ピカチュウ
// 検索結果
コダック コラッタ ズバット ギャロップ ピカチュウ
文字クラス内でのAND条件は &&
文字クラス内でも「&&」を使えばAND条件のような表現が可能です。たとえば「^[0-9&&[^1]]+$」とかくと、「0-9の数値」かつ「1以外の文字」という形でAND条件を表します。こちらも詳細が長くなるため、下記の解説にて割愛します。