Python 正则表达式反向引用命名组

Python Regex back reference a named group

我正在尝试解析 phone 可以通过不同方式获得的数字。例如:

(321) 123-4567
(321) 1234567
321-123-4567
321123-4567

然后我想分别绘制这三个部分中的每一个。我的想法是使用命名组和一些和/或这样的情况:

(^\s*(?P<area>[0-9]{3})\-?(?P<fst>[0-9]{3})\-(?P<lst>[0-9]{4}))|(^\s*\(\area\)\s*(\fst)\-?(\lst))

我认为问题在于我没有正确调用命名组。我正在尝试使用 https://regex101.com/ 来提供帮助,但仍然卡住了。因为区号周围的括号要么都存在,要么都不存在,所以我不想使用“?”像这样的字符:

\(?(?P<area>[0-9]{3})\)?

谁能帮我解决这个问题?太感谢了。

我正在使用 python 3.6 和 re 包。

您的正则表达式存在一些问题。您没有将方括号设为可选,并且您不允许在区号和第一部分之间使用可选空格。如果没有看到您的 Python 代码,就很难知道您是如何做的,但我是通过拆分成一个已编译的正则表达式,然后对数字列表使用正则表达式来做到这一点的。

from __future__ import print_function
import re

phone_numbers = [
'(321) 123-4567',
'(321) 1234567',
'321-123-4567',
'321123-4567',
]

regex = re.compile(r'^\s*\(?(?P<area>[0-9]{3})[) -]*(?P<fst>[0-9]{3})-?(?P<sec>[0-9]{4})')

for p in phone_numbers:
    print(regex.sub(r'(\g<area>) \g<fst>-\g<sec>', p))

这并不完美,因为它允许解析无效语法(根据您的列表),但这应该不是问题。例如 '(321))- - )) 123-4567' 将被正确解析。

我会使用小组测试:^(\()?(?P<area>\d{3})(?(1)\))[ -]?(?P<fst>\d{3})-?(?P<lst>\d{4})$

在那里:

  • (\()? 捕获第 1 组中存在的左括号。
  • (?(1)\)) 测试捕获组 1 是否存在,如果匹配右括号。

剩下的就很简单了。