用于清理姓名变体的Python re.compile函数及正则表达式模式
我在寻找一个正则表达式模式,帮助我把名字整理成仅包含名、姓和后缀的形式。它需要能够处理以下变体。
- 去掉任何中间名
- 若存在姓氏,则保留姓氏
- 去掉任何昵称
- 去掉任何婚前名或曾用名,标准格式为 (name-)
- 保留后缀,且后缀不带标点符号。始终跟在姓氏后的逗号和空格之后。
- 不保留贵族头衔。始终跟在姓氏后的逗号和空格之后。
Sarah Michelle Gellar -> Sarah Gellar
Leslie Marie DeGuzman Santorini -> Leslie Santorini
Beyonce -> Beyonce
Stefani "Lady Gaga" Germanotta -> Stefani Germanotta
Lebron James, Jr. -> Lebron James Jr
Hailey Bieber (Baldwin-) -> Hailey Bieber
Shania (Irene-) Twain -> Shania Twain
Charles "Chaz" Fluffy Wong, Duke of CatTown -> Charles Wong
我尝试了几种不同的REGEX模式,仍然无法弄清楚如何用一个模式覆盖所有这些情况。以下是我最近的尝试。
re_names = re.compile(r'''^
\s*
(?P<first>[a-zA-Z.'\-]+)
(?P<middle>(\s[a-zA-Z.'"\-\(\)]+)*)?
(?P<last>\s[a-zA-Z.'\-]+)?
(?P<maiden>(\s\([a-zA-Z,.'"\-]+\)*))?
(,\s)?
(?P<suffix>([a-zA-Z'\-]+)*)?
.*
$
''',
re.VERBOSE)
不幸的是,这个模式把第一个名字之后的所有名字都作为中间名。它还把 "Duke" 捕捉为最后一个测试用例的后缀,而实际上应该没有后缀。
我也考虑过使用独立的re.compile与独立的REGEX模式,但仍然找不到一种方法可以成功覆盖所有情况。
解决方案
你真的应该避免使用如此复杂的模式,以防止灾难性回溯。但如果你坚持,以下模式将使用非贪婪量词来匹配你提供的8 种情况中的全部(*?, +?, ??)。解释请参见此处。
import re
pattern = r"""
^
(?P<first>\S+?)
(?P<last>\s\S+?)*?
(?P<maiden>\s\(\S+?-\))??
(?P<title>,\s.+?)??
(,(?P<suffix>\s(Jr|Sr|II|III|IV))\.??)??
$
"""
repl = r'\g<first>\g<last>\g<suffix>'
strings = [
'Sarah Michelle Gellar',
'Leslie Marie DeGuzman Santorini',
'Beyonce',
'Stefani "Lady Gaga" Germanotta',
'Lebron James, Jr.',
'Hailey Bieber (Baldwin-)',
'Shania (Irene-) Twain',
'Charles "Chaz" Fluffy Wong, Duke of CatTown',
]
for string in strings:
print(re.sub(pattern, repl, string, flags=re.VERBOSE))
Sarah Gellar
Leslie Santorini
Beyonce
Stefani Germanotta
Lebron James Jr
Hailey Bieber
Shania Twain
Charles Wong
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。