正则表达式提取姓名:排除头衔并支持多姓名与双姓
问题
需要从700份格式一致但数据不同的PDF文件中提取姓名及其他数据。使用PDFPig提取PDF文本后,通过正则表达式提取特定内容,但当前正则未覆盖以下两种场景,导致提取错误:
- (a)支持多姓名/双姓(如示例中的
Helen King作为姓氏) - (b)排除姓名前缀的
Mr、Mrs、Miss等头衔(当前会把Ms误识别为名)
当前正则表达式:
"\b[A-ZÜÄÖ][a-züßäö]{3,}\s[A-ZÜÄÖ][a-züßäö]{3,}\b"
代码上下文:
private void name_extraction() { string namePattern = @"\b([A-ZÜÄÖ][a-züßäö]+)\s+(?:[A-ZÜÄÖ][a-züßäö]+\s*)*([A-ZÜÄÖ][a-züßäö]+)\b"; /*@"\b[A-ZÜÄÖ][a-züßäö]{3,}\s[A-ZÜÄÖ][a-züßäö]{3,}\b";*/ Regex nameRegex = new Regex(namePattern); Match nameMatch = nameRegex.Match(parsed_text.ToString()); if (nameMatch.Success) { string extractedName = nameMatch.Value; int spaceIndex = extractedName.IndexOf(' '); string firstName = extractedName.Substring(0, spaceIndex); string lastName = extractedName.Substring(spaceIndex + 1); extracted_data["FirstName"] = firstName; extracted_data["LastName"] = lastName; account_year_extraction(); } else { MessageBox.Show("Name was not extracted!" + "\n" + "Check formatting of input file."); } }
输入文本示例:
Confidential - Ms Jennifer Helen King - account type and date.
期望输出:
FirstName: Jennifer
LastName: Helen King
实际错误输出:
FirstName: Ms
LastName: Jennifer Helen King Re Mrs
咨询:是否可通过正则表达式实现排除头衔、支持双姓的姓名提取,还是需提取后再做后续处理?
解决方案
可以通过优化正则表达式直接实现排除头衔+支持多姓名/双姓的提取,无需额外后续处理,具体调整如下:
1. 核心思路
- 先定义需要排除的头衔列表(
Mr、Mrs、Ms、Miss等),用负向预查排除这些前缀 - 允许姓名中包含多个中间名/双姓,同时区分名和姓的结构(示例中
Jennifer是名,Helen King是双姓)
2. 调整后的正则表达式
@"\b(?!(Mr|Mrs|Ms|Miss)\s)[A-ZÜÄÖ][a-züßäö]+\s+((?:[A-ZÜÄÖ][a-züßäö]+\s?)+)\b"
(?!(Mr|Mrs|Ms|Miss)\s):负向预查,排除以指定头衔开头的内容- 第一个捕获组:匹配单个名字(如
Jennifer) - 第二个捕获组:匹配后续的所有姓氏部分(支持多词,如
Helen King)
3. 代码修改
把原代码中的正则替换为上述表达式,并调整姓名拆分逻辑(不再用第一个空格分割,直接用捕获组):
private void name_extraction() { // 定义需要排除的头衔,可根据实际情况补充 string excludedTitles = @"Mr|Mrs|Ms|Miss"; string namePattern = $@"\b(?!({excludedTitles})\s)[A-ZÜÄÖ][a-züßäö]+\s+((?:[A-ZÜÄÖ][a-züßäö]+\s?)+)\b"; Regex nameRegex = new Regex(namePattern); Match nameMatch = nameRegex.Match(parsed_text.ToString()); if (nameMatch.Success) { // 直接从捕获组获取名和姓 string firstName = nameMatch.Groups[1].Value; string lastName = nameMatch.Groups[2].Value.Trim(); // 去除末尾可能的空格 extracted_data["FirstName"] = firstName; extracted_data["LastName"] = lastName; account_year_extraction(); } else { MessageBox.Show("Name was not extracted!" + "\n" + "Check formatting of input file."); } }
4. 补充说明
- 如果后续遇到新的头衔,直接在
excludedTitles中添加即可 - 若PDF中姓名结构有其他变体(如带后缀
Jr、Sr),可以在正则中进一步调整(比如在最后添加负向预查排除后缀) - 由于所有PDF格式一致,这个正则可以稳定适配大部分场景
内容的提问来源于stack exchange,提问作者AliceSkarre
相关产品推荐
相关产品推荐

