web-dev-qa-db-ja.com

Pythonで複数の正規表現を単一のものに組み合わせる方法は?

正規表現について学んでいます。異なる正規表現を組み合わせて単一の汎用正規表現を作成する方法がわかりません。

複数のケースで機能する単一の正規表現を書きたいのですが。これはor"|"演算子を使用することにより、素朴なアプローチで実行できることを知っています。

このアプローチは好きではありません。誰かが私にもっと良いアプローチを教えてくれますか?

15
Amit

すべての正規表現関数をコンパイルする必要があります。この例を確認してください:

import re
re1 = r'\d+\.\d*[L][-]\d*\s[A-Z]*[/]\d*'
re2 = '\d*[/]\d*[A-Z]*\d*\s[A-Z]*\d*[A-Z]*'
re3 = '[A-Z]*\d+[/]\d+[A-Z]\d+'
re4 = '\d+[/]\d+[A-Z]*\d+\s\d+[A-z]\s[A-Z]*'

sentences = [string1, string2, string3, string4]
generic_re = re.compile("(%s|%s|%s|%s)" % (re1, re2, re3, re4)).findall(sentence)
6
Lior Magen

任意の一連のREをfindallにするには、それぞれが返す一致のリストを連結するだけです。

re_list = [
    '\d+\.\d*[L][-]\d*\s[A-Z]*[/]\d*', # re1 in question,
    ...
    '\d+[/]\d+[A-Z]*\d+\s\d+[A-z]\s[A-Z]*', # re4 in question
]

matches = []
for r in re_list:
   matches += re.findall( r, string)

効率を上げるには、コンパイル済みのREのリストを使用することをお勧めします。

または、次のコマンドを使用して要素RE文字列を結合することもできます

generic_re = re.compile( '|'.join( re_list) )
1
nigel222

多くの人がパイプを使用しているようですが、それは最初のインスタンスにのみ一致するようです。すべてを一致させたい場合は、先読みを使用してみてください。

例:

_>>> fruit_string = "10a11p" 
>>> fruit_regex = r'(?=.*?(?P<pears>\d+)p)(?=.*?(?P<apples>\d+)a)'
>>> re.match(fruit_regex, fruit_string).groupdict()
{'apples': '10', 'pears': '11'}
>>> re.match(fruit_regex, fruit_string).group(0)
'10a,11p'
>>> re.match(fruit_regex, fruit_string).group(1)
'11'
_

_(?= ...)_は先読みです:

...が次に一致する場合に一致しますが、文字列を消費しません。これは先読み表明と呼ばれます。たとえば、Isaac(?= Asimov)は、「Asimov」が後に続く場合にのみ「Isaac」と一致します。

.*?(?P<pears>\d+)p文字列の任意の場所でpの後に続く数字を検索し、その数字に「pears」という名前を付けます

0
Karen McCulloch