用于清理姓名变体的Python re.compile函数及正则表达式模式

编程语言 2026-07-09

我在寻找一个正则表达式模式,帮助我把名字整理成仅包含名、姓和后缀的形式。它需要能够处理以下变体。

  1. 去掉任何中间名
  2. 若存在姓氏,则保留姓氏
  3. 去掉任何昵称
  4. 去掉任何婚前名或曾用名,标准格式为 (name-)
  5. 保留后缀,且后缀不带标点符号。始终跟在姓氏后的逗号和空格之后。
  6. 不保留贵族头衔。始终跟在姓氏后的逗号和空格之后。

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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章