0

几天来,我一直在调整一个正则表达式,试图用一个定义来捕获数据库地址字段中格式不一致的几种情况。

我是 Python 和正则表达式的新手,在这里得到了很好的反馈是 stackoverflow,并且根据我的新知识,我构建了一个接近最终结果的 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 个在 'caracas' 末尾有一个额外的空间。提前感谢您的任何见解。

干杯!

4

2 回答 2

1

正则表达式可能有点矫枉过正......你的问题陈述到底是什么?你需要捕捉什么?

我捕捉到的一些东西(按您的正则表达式中出现的顺序;有时它有助于读出它,从左到右,英文风格):

([\w\s+]+)

这就是说,“捕获一个或多个(字母或一个或多个空格)”

您真的要捕获城市名称末尾的空格吗?此外,您不需要(实际上不应该有)+括号内的 1 个或多个符号[ ],因为您的正则表达式已经根据外部匹配其中一个或多个符号+。我会这样重写这部分:

([\w\s]*\w)

它将热切匹配到最后一个字母数字字符(“零个或多个(字母或空格)后跟一个字母”)。这确实假设您至少有一个字符,但比您假设单个空格也可以工作要好。

接下来你有:

,?\s*\(?

这对我来说看起来不错,只是它不能保证你会再看到逗号或左括号。关于什么:

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

它说,“非捕获匹配(可能有一些空格的逗号,然后是一个开放的括号)或(可能有一些空格的逗号)或(可能是一些空格,然后是一个开放的括号)”。这强制您必须有逗号或括号或两者都有。

接下来是捕获表达式,与第一个非常相似:

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

同样,您不希望城市名称末尾的空格(或在这种情况下为斜杠),并且您不希望+[ ]:

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

下一个表达式可能是您遇到venezuel a问题的地方;让我们来看看:

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

这是一个相当长的问题,所以让我们分解一下:

\)?\s*\(?

说“可能匹配一个封闭的括号,然后可能是一些空格,然后可能是一个开放的括号”。我猜这没关系,让我们继续讨论真正的问题:

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

此捕获组必须匹配至少一个字符。如果匹配器在您的地址末尾看到“venezuela”,它将急切地匹配字符venezuel,然后需要用它剩下的内容来满足这个最终表达式,a. 请尝试:

\)?\s*

然后使您的整个最终表达式可选,并且外部表达式不捕获:

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

最后的表达式是:

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

编辑:修复了导致最终组捕获两次的问题,一次有括号,一次没有。现在它应该只捕获括号内的文本。

在您的示例上对其进行测试:

>>> 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 回答