0

私は数日間にわたって正規表現を微調整して、データベースのアドレスフィールドで一貫性のない形式のいくつかのケースを単一の定義でキャプチャしようとしています。

私はPythonと正規表現に不慣れで、ここでスタックオーバーフローについて大きなフィードバックを得ています。新しい知識を使って、最終結果に近づいているRegExを作成しましたが、それでも問題を特定できません。

import re

r1 = r"([\w\s+]+),?\s*\(?([\w\s+\\/]+)\)?\s*\(?([\w\s+\\/]+)\)?"

match1 = re.match(r1, 'caracas, venezuela')
match2 = re.match(r1, 'caracas (venezuela)')
match3 = re.match(r1, 'caracas, (venezuela) (df)')

group1 = match1.groups()
group2 = match2.groups()
group3 = match3.groups()

print group1
print group2
print group3

これにより、グループ1と2の場合は「caracas、venezuela」が返され、グループ3の場合は「caracas、venezuela、df」が返されます。代わりに、次のように返されます。

('caracas', 'venezuel' 'a') 
('caracas ', 'venezuel' 'a')
('caracas', 'venezuela', 'df')

唯一の完全一致はグループ3です。他の2つは、最後に「a」を分離し、2つ目は「カラカス」の最後に余分なスペースがあります。洞察を事前に感謝します。

乾杯!

4

2 に答える 2

1

正規表現はやり過ぎかもしれません...あなたの問題の記述は正確には何ですか?何をキャプチャする必要がありますか?

私が捕まえたいくつかのこと(あなたの正規表現に現れる順序で;時々それを読むのに役立つ、左から右、英語スタイル):

([\w\s+]+)

これは、「1つ以上(文字または1つ以上のスペース)をキャプチャする」という意味です。

都市名の末尾のスペースを本当にキャプチャしますか?また、正規表現はすでに外側に基づいて1つ以上の記号と一致しているため、+角かっこ内に1つ以上の記号は必要ありません(実際には必要ありません)。この部分を次のように書き直します。[ ]+

([\w\s]*\w)

これは、最後の英数字(「ゼロ以上(文字またはスペース)の後に文字が続く」)まで熱心に一致します。これは、少なくとも1つの文字があることを前提としていますが、単一のスペースでも機能するという想定よりも優れています。

次にあります:

,?\s*\(?

これは、コンマまたは開いたパレンのいずれかが表示されることを保証しないことを除いて、私には問題ないように見えます。どうですか:

(?:,\s*\(|,\s*|\s*\()

これは、「(スペースがいくつかあり、次に開き括弧があるコンマ)OR(スペースがいくつかあるコンマ)OR(スペースがあり、次に開き括弧があるコンマ)のいずれかに非キャプチャー一致します。これにより、コンマまたはパレン、あるいはその両方が必要になります。

次に、最初の式と非常によく似たキャプチャ式があります。

([\w\s+\\/]+)

+繰り返しになりますが、都市名の末尾にスペース(この場合はスラッシュ)を付けたり、内部にスペースを入れたりする必要はありません[ ]

([\w\s\\/]*\w)

次の表現は、おそらくvenezuel a問題が発生している場所です。見てみましょう:

\)?\s*\(?([\w\s+\\/]+)\)?

これはかなり長いので、分解してみましょう。

\)?\s*\(?

「多分近いパレン、そして多分いくつかのスペース、そして多分開いたパレンと一致する」と言います。これは大丈夫だと思います。本当の問題に移りましょう。

([\w\s+\\/]+)

このキャプチャグループは、少なくとも1つの文字と一致する必要があります。マッチャーがあなたの住所の最後に「ベネズエラ」を見つけた場合、それは熱心に文字と一致しvenezuel、次にこの最終的な表現をそれが残したもので満たす必要がありaます。代わりに試してください:

\)?\s*

続いて、最終式全体をオプションにし、外側の式をキャプチャしないようにします。

(?:\(?([\w\s+\\/]+)\)?)?

最終的な式は次のようになります。

([\w\s]*\w)(?:,\s*\(|,\s*|\s*\()([\w\s\\/]*\w)\)?\s*(?:\(?([\w\s+\\/]+)\)?)?

編集:最終的なグループを2回キャプチャする問題を修正しました。1回はペアレンあり、もう1回はペアなしです。これで、parens内のテキストのみをキャプチャする必要があります。

あなたの例でそれをテストします:

>>> re.match(r, 'caracas, venezuela').groups()
('caracas', 'venezuela', None)
>>> re.match(r, 'caracas (venezuela)').groups()
('caracas', 'venezuela', None)
>>> re.match(r, 'caracas, (venezuela) (df)').groups()
('caracas', 'venezuela', 'df')
于 2012-04-05T23:19:32.090 に答える
0

テキスト内のすべての単語を見つけることができませんでしたか?

例えば:

>>> import re
>>> samples = ['caracas, venezuela','caracas (venezuela)','caracas, (venezuela) (df)']
>>>
>>> def find_words(text):
...   return re.findall('\w+',text)
...
>>> for sample in samples:
...   print find_words(sample)
...
['caracas', 'venezuela']
['caracas', 'venezuela']
['caracas', 'venezuela', 'df']
于 2012-04-05T22:45:16.117 に答える