正则表达式:匹配一个模式并排除另一个模式

3
我有一个匹配电话号码的正则表达式:
import re
phones = re.findall(r'[+(]?[0-9][0-9 \-()]{8,}[0-9]', text)

它在一个大的原始文本数据集中表现出很好的准确性。

但有时会匹配到不想要的结果(年份范围和随机ID)。

年份范围:

'2012 - 2017'
'(2011 - 2013'
'1999                                                   02224'
'2019     2010-2015'
'2018-2018 (5'
'2004 -2009'
'1) 2005-2006'
'2011            2020'

随机ID:

'5                    5                    5                 5'
'100032479008252'
'100006711277302'

我有一些解决这些问题的想法。

  1. 将总位数限制为12位数字。
  2. 将总字符数限制为16个字符。
  3. 删除年份范围(19**|20** - 19**|20**)。

但我不知道如何实现这些想法,并将它们作为我的正则表达式中的异常。

下面是一些正则表达式应该捕获的示例:

380-956-425979
+38(097)877-43-88
+38(050) 284-24-20
(097) 261-60-52
380-956-425979
(068)1850063
0975533222

尝试精准地确定模式,而不是添加排除项。例如 \+?(?:\([0-9]{1,4}\)|\b[0-9]{1,4}|\b)[0-9](?:[ -]?[0-9]){8}(?!\d)\+?(?:\([0-9]{1,3}\)|\b[0-9]{1,3}|\b)[0-9](?:[ -]?[0-9]){9}(?!\d)。在大多数情况下,后处理匹配结果会比尝试将所有内容压缩到单个模式中更安全。 - Wiktor Stribiżew
@WiktorStribiżew,与先前的表达式不同,这些正则表达式无法捕获以下示例: '380-936-745979' '+38(093)797-43-82' '+38(098)278-33-20' '(095)356-44-52' '380-986-898979' '(069)1960063' - lemon
尚未完全测试:text = "+(123) 1234-1234" phones = re.findall(r'\+?(?:\(\d{3}\)|\d{3}) ?\d{4}\-?\d{4}', text) - Frank
@Frank,很遗憾,我的评论中没有任何示例被捕获。 - lemon
2个回答

1

我建议您为不同的手机结构编写不同的模式。我不太确定您的电话号码结构,但这与您的示例相匹配:

import re
test = '''380-956-425979
+38(097)877-43-88
+38(050) 284-24-20
(097) 261-60-52
380-956-425979
(068)1850063
0975533222'''
solution = test.split("\n")

p1 = "\+?\d{3}\-\d{3}\-\d{6}"
p2 = "\+?(?:\d{2})?\(\d{3}\) ?\d{3}\-\d{2}\-\d{2}"
p3 = "\+?\d{3}\-\d{3}\-\d{6}"
p4 = "\+?(?:\(\d{3}\)|\d{3})\d{7}"

result = re.findall(f'{p1}|{p2}|{p3}|{p4}', test)
print(solution)
print(result)

0
你可以直接在Python中完成它:
if regex.match("condition", "teststring") and not regex.match("not-condition", "teststring"):
   print("Match!")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接