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

2024-10-01 07:40:59 发布

您现在位置:Python中文网/ 问答频道 /正文

考虑这个Python regex来查找电话号码:

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

问题是,这将匹配任何长度至少为10个字符的数字字符串,因此我需要确保如果regex前面有一个字符,那么它就不能是数字。你知道吗

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

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的regex在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

在应用程序中,我在一个列表中运行regex:

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

Tags: 字符串textinresearchismatch电话号码
1条回答
网友
1楼 · 发布于 2024-10-01 07:40:59

使用否定的lookback断言:

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

我在结尾也加入了负面展望。否定的lookbehind和lookahead断言只匹配文本中的位置,而该位置前面或后面的文本不匹配模式。你知道吗

这类似于^$锚定,因为它们也匹配特定的位置,而不是字符本身。在文本'a1b2c'中,字符串的开头以及abc之后的位置都与(?<!\d)负向后看匹配,因为在这些位置,前面的字符不是数字(在开头根本没有字符)。你知道吗

仅当模式前面没有数字,模式后面没有数字时,使用这些使模式匹配;字符串的开头和结尾也在这里限定。你知道吗

快速演示:

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

相关问题 更多 >