small is beautiful

be the worst

Python: /regexp?/ (正規表現)

Pythonのおべんきょう

re module

  • re.sub は正規表現パターンで引数に渡された文字列を置換する。
    • re.sub(<pattern>, <置換後の文字列>, <置換対象の文字列>, [置換回数])
>>> import re
>>> test_str = '123 ABC DEF ABCDEF'

>>> re.sub('^123', '123 456', test_str)
'123 456 ABC DEF ABCDEF'

>>> re.sub('^DEF', 'DEF GHI', test_str)
'123 456 ABC DEF ABCDEF'

# add string to end.
>>> re.sub('$', 'GH', test_str)
'123 ABC DEF ABCDEFGH'
  • \b で (単独な) 単語を指定可能。
  • r (raw string) を利用しない場合はescapeが必要だが、正規表現は r を使うことで都度エスケープする必要がなくなる。
  • \1は置き換えするgroupの番号(順番)を指す。
>>> import re
>>> test_str = '123 ABC DEF ABCDEF'

>>> re.sub('\\bDEF', 'def', test_str)
'123 ABC def ABCDEF'

>>> re.sub(r'\bdef', 'DEF', test_str)
'123 ABC DEF ABCDEF'

>>> re.sub('([^abc]r$)', r'\1s', 'engineer')
'engineers'

search()

  • 最初から最後まで一致するものを探す。
    • ※ match()は、 先頭との一致。
  • ?x は1つのxという文字に任意でマッチする。
    • xが0、 若しくは1回の出現でマッチする。
  • $, ^ が一緒に使われると (^ABC$) 文字列が全一致する必要がある。
  • [] 内の ^ は否定を表す。 []内に一致しない文字列であれば一致する。
    • [^123] は1,2,3のどれかでは無い文字列である。
>>> p = '^123 A?B?C'

>>> re.search(p, '123 C')
<re.Match object; span=(0, 5), match='123 C'>
>>> re.search(p, '123 BC')
<re.Match object; span=(0, 6), match='123 BC'>
>>> re.search(p, '123 ABC')
<re.Match object; span=(0, 7), match='123 ABC'>

>>> p = '^[^123]\D*ABC'

>>> re.search(p, '1 ABC')
>>> re.search(p, '123 ABC')
>>> re.search(p, '4 ABC')
<re.Match object; span=(0, 5), match='4 ABC'>
>>> re.search(p, 'D-ABC')
<re.Match object; span=(0, 5), match='D-ABC'>
  • {x, y} はx以上y以下に一致する。
    • {x} のみだとx桁の数字の意味。
>>> p = 'engine{0,2}r'

>>> re.search(p, 'enginer')
<re.Match object; span=(0, 7), match='enginer'>
>>> re.search(p, 'engineer')
<re.Match object; span=(0, 8), match='engineer'>
>>> re.search(p, 'engineeer')
  • [] はどれか一文字に一致する。
>>> p = re.compile(r'^0[78]0\D*\d{4}\D*\d{4}$')

>>> p.search('080-1234-5678')
<re.Match object; span=(0, 13), match='080-1234-5678'>
>>> p.search('070-1234-5678')
<re.Match object; span=(0, 13), match='070-1234-5678'>

冗長な正規表現

  • 次の例ではあまり意味を成していないが、 正規表現が複雑な場合は冗長な正規表現で分かりやすくする。
  • re.VERBOSE (若しくは re.X) が引数に必要。
>>> p = '''
... ^                   # beginning of e
... engine{0,2} # e apper 0 to 3 times
... r$                # end of r
... '''
>>> re.search(p, 'engineer')
>>> re.search(p, 'engineer', re.VERBOSE)
<re.Match object; span=(0, 8), match='engineer'>

method

method description
match() 文字列の先頭でmatch
search() 文字列の全体を探す
findall() 正規表現に一致する部分文字列を全て探しlistで返す
finditer() 正規表現に一致する部分文字列を全て探しiteratorで返す

正規表現のcompile

  • 正規表現のcompileが可能。
  • groups() は正規表現のparserがアクセスした一致した文字列をtupleで返す。
  • \d は任意の数字を意味する。
  • \D は数字を除く全ての文字列に一致する。
  • + は1回以上を意味する。
    • \D+1 だと数字を除く全ての文字列に合致する。
  • * は0回以上を意味する。
>>> p = re.compile(r'\d{3}\D*\d{4}\D*\d{4}$')
>>> p.search('080-1234-5678')
<re.Match object; span=(0, 13), match='080-1234-5678'>
>>> p.search('080-1234-5678').groups()
()

>>> p = re.compile(r'^(\d{3})\D*(\d{4})\D+(\d{4})$')
>>> p.search('080-1234-5678')
<re.Match object; span=(0, 13), match='080-1234-5678'>
>>> p.search('080-1234-5678').groups()
('080', '1234', '5678')