home changes contents help options

072:文字列が複数の正規表現のすべてにマッチするか調べる

個々の正規表現にマッチさせてみる

文字列が複数の正規表現のすべてにマッチするかどうかを調べる方法は、

  1. 正規表現1つにマッチさせてみる。
  2. マッチしなければ「すべてにマッチはしない」と判断。マッチした場合は他の正規表現にマッチさせてみる。繰り返し。
  3. すべての正規表現にマッチしたら「すべてにマッチする」と判断。

で問題ありません。

import re

def search_all(s, *re_list):
    u"""
    引数に文字列 s と正規表現オブジェクトをとり、
    文字列 s がすべての正規表現にマッチするかどうかを調べる。
    正規表現オブジェクトは複数の指定が可能。
    """
    for r in re_list:
        if not r.search(s):
            return False
    return True

def search_all_s(s, *str_list):
    u"""
    引数に文字列 s と正規表現を示す文字列をとり、
    文字列 s がすべての正規表現にマッチするかどうかを調べる
    正規表現を示す文字列は複数の指定が可能。
    """
    for str_ in str_list:
        if not re.search(str_, s):
            return False
    return True
>>> import re
>>> s = 'aaabbc'
>>> search_all_s(s, 'aa', 'bb')
True
>>> search_all_s(s, 'aa', 'bb', 'cc')
False
>>>
>>> re_list = [
...   re.compile(r'aa'),
...   re.compile(r'bb'),
...   ]
>>> search_all(s, *re_list) # search_all(s, re.compile(r'aa'), re.compile(r'bb'),) と同義
True
>>> re_list.append(re.compile('cc'))
>>> search_all(s, *re_list)
False

Python 2.5 で追加された組み込み関数 all と Python 2.4 で追加された ジェネレータ式 を用いると 1行で実装することができます。

import re

def search_all(s, *re_list):
    u"""
    引数に文字列 s と正規表現オブジェクトをとり、
    文字列 s がすべての正規表現にマッチするかどうかを調べる。
    正規表現オブジェクトは複数の指定が可能。
    """
    return all(r.search(s) for r in re_list)

def search_all_s(s, *str_list):
    u"""
    引数に文字列 s と正規表現を示す文字列をとり、
    文字列 s がすべての正規表現にマッチするかどうかを調べる
    正規表現を示す文字列は複数の指定が可能。
    """
    return all(re.search(str_, s) for str_ in str_list)

あえて正規表現で解いてみる

文字列が複数の正規表現のすべてにマッチするかどうかを調べる正規表現を作成します。 先読みアサーション '(?= )' を用います。 正規表現 A, B, C があるとすると求める正規表現は (?=A)(?=B)(?=C) となります。

import re

def search_all2(s, *re_list):
    u"""
    引数に正規表現オブジェクト(複数可)をとり、
    すべてにマッチするかどうかを調べる
    """
    str_list = [r.pattern for r in re_list]
    return search_all2_s(s, *str_list)

def search_all2_s(s, *str_list):
    u"""
    引数に正規表現を示す文字列(複数可)をとり、
    すべてにマッチするかどうかを調べる
    """
    return re.search(
            ''.join([r'(?=.*%s)' % str_ for str_ in str_list]),
            s,
            re.DOTALL,
            )

前述の個々の正規表現にマッチさせる方法と異なり、マッチオブジェクトか None が返ります。 しかし、このように先読みのみで作られた正規表現が返すマッチオブジェクトには 役に立つ情報が含まれていないためとくにメリットはありません。 前述の方法を使うほうがよいでしょう。