🙌

正規表現でANDってどうやるの?

2023/01/13に公開

はじめに

OR表現は|でやれば良いけどANDがどうやるのかわからなかったので、今更調べてみました。
ついでにメタ文字についてもまとめておきます。

メタ文字

正規表現で利用する特殊文字をメタ文字と呼びます。
これらを利用しより高度な表現を実現します。

  • .
    何でもいい1文字
  • ^
    行の先頭
    先頭の場合のみメタ文字として認識
  • $
    行の最後
    終端の場合のみメタ文字として認識
  • *
    直前の文字の0個以上の連続
    .と組み合わせた時の挙動としては可能な限り合致するものまでつながる
  • +
    直前の文字の1個以上の連続
  • ?
    直前の文字が0個か1個
  • |
    いずれかの文字列に一致
    Java|Kotlin|Groovyの様に利用
  • []
    括られた中の文字のどれか一つ
    [A-Z](大文字AからZまでを表現している)の様に利用
    注意点
    • 先頭で^が使われた場合は否定の意味になる([^A-Z]=AからZ以外)
    • 基本的に文字コードで管理されているので全角文字で利用するときには注意が必要
    • 基本メタ文字は通常文字として認識される
      • ^を通常文字で使いたい場合は2文字目以降でないと無理
      • ただし]\はエスケープが必要
  • ()
    グループ化してまとめて処理できる
    (正規)+にすると()でグループ化された「正規」という文字列に対して+が有効になる

ANDの表現

AND表現はシンプルにはいかないため、肯定先読みを利用します。

肯定先読みとは?

(?=)で表現します。
正規表現的には以下の挙動を言います。

  • 処理位置の前方方向へ向かって文字列のAssertionを行う
  • マッチングがあれば、そのまま処理位置に戻って処理を再開する

わかりにくいと思いますが、例えば^(?=.*わたし).*$という正規表現があったとして、これにマッチするのは「わたしの記事」、「このメモはわたしのもの」みたいになります。
この挙動を紐解くと、肯定先読みの挙動であるマッチングした後に処理位置を戻す動きのおかげで、「わたし」にマッチング後、その後の.*が文頭から文章全体にマッチングしてくれるので文字列の部分一致ができることになります。

AND表現

上記の肯定先読みの仕組みを応用して、例えば^(?=.*わたし)(?=.*あなた).*$とすると「わたし」と「あなた」が両方マッチすることの確認が可能となり、ANDで文字列がマッチする正規表現が記述できます。

否定先読みとは?

また、これまでは一致しているものでしたが、否定もできます。
その場合は(?!)で表現します。
例えば^(?=.*わたし)(?!.*あなた).*$とすると「わたし」にマッチし、「あなた」にマッチしない正規表現が記述できます。

まとめ

業務では簡単な正規表現しか使ってこなかったので、先読みという知識がなかったですが、これで上手く組み立てれました。
調べていく中でまだまだ知らない知識がかなりありそうだったので、正規表現は奥深いですね(苦笑

Discussion