正则表达式:如果有一个字符,那么它不能是一个数字

时间:2013-12-10 10:57:39

标签: python regex

考虑使用此Python正则表达式来查找电话号码:

reg = re.compile(".*?(\(?\d{3}\D{0,3}\d{3}\D{0,3}\d{4}).*?", re.S)

问题是这将匹配长度至少为10个字符的任何数字字符串,因此我需要确保如果正则表达式之前有一个字符,则它不能是数字。

这不起作用,因为如果电话号码是字符串的开头,它就会中断:

reg = re.compile(".*?\D(\(?\d{3}\D{0,3}\d{3}\D{0,3}\d{4}).*?", re.S)

这不起作用,因为之前的.*?可能以数字结尾:

reg = re.compile(".*?[\D]?(\(?\d{3}\D{0,3}\d{3}\D{0,3}\d{4}).*?", re.S)

有什么用?

修改

Martijn的正则表达式在match上中断,即使它适用于search

>>> text = 'The Black Cat Cafe is located at 45 Main Street, Irvington NY 10533, in one of the \nRiver Towns of Westchester. ..... Our unique menu includes baked ziti pizza, \nchicken marsala pizza, margherita pizza and many more choices. ..... 914-232-2800 ...... cuisine, is located at 36 Main Street, New Paltz, NY 12561 in Ulster \nCounty.'
>>> reg = re.compile(r"(?<!\d)(\(?\d{3}\D{0,3}\d{3}\D{0,3}\d{4})(?!\d)", re.S)
>>> reg.search(text).groups()[0]
'914-232-2800'
>>> reg.match(text) is None
True
>>> reg_dotan = re.compile(".*?(\(?\d{3}\D{0,3}\d{3}\D{0,3}\d{4}).*?", re.S)
>>> reg_dotan.search(text).groups()[0]
'914-232-2800'
>>> reg_dotan.match(text) is None
False

在应用程序中,我正在列表解析中运行正则表达式:

have_phones = [d for d in descriptions if reg.match(d)]

1 个答案:

答案 0 :(得分:1)

使用负面的lookbehind断言:

reg = re.compile(r"(?<!\d)(\(?\d{3}\D{0,3}\d{3}\D{0,3}\d{4})(?!\d)", re.S)

我最后还包括了一个负面的前瞻。负向lookbehind和lookahead断言仅匹配文本中的位置,其中此位置之前或之后的文本与模式匹配。

这就像^$锚一样,因为它们也匹配特定的位置,而不是字符本身。在文字'a1b2c'中,字符串的开头以及 a后的位置,bc都匹配(?<!\d)负面的背后,因为在那些位置,前面的字符不是数字(开头时根本没有字符)。

使用这些模式只有在前面没有数字且模式后面没有数字时才会匹配模式;字符串的开头和结尾也符合条件。

快速演示:

>>> reg.search('0123456789')          # 10 digits
<_sre.SRE_Match object at 0x1026ea468>
>>> reg.search('10123456789') is None # 11 digits
True