使用Regex生成Token时的标点符号特殊场景处理
解决特殊标点场景下的句子拆分问题
原代码通过直接匹配所有标点符号进行拆分,会误处理域名(如abc.io)、数字千分位逗号(如10,000)这类属于内容一部分的标点,导致拆分结果不符合预期。
核心解决思路是排除不需要拆分的标点场景,只在真正的句子分隔标点处拆分。以下是两种可行方案:
方案一:优化拆分正则(re.split)
使用正则的负向断言精准排除域名点、数字千分位逗号等特殊场景,仅在句子终结标点或非千分位逗号处拆分:
import re def split_sentences(text): # 拆分规则: # 1. 排除域名/缩写里的点(如abc.io、Mr.):点前后为字母/数字 # 2. 排除数字千分位逗号(如10,000):逗号前后为数字 # 3. 仅在句子终结标点(.!?)或非千分位逗号处拆分 pattern = r'(?<!\w)\.(?!\w)|(?<!\d),(?!\d)|[!?]' parts = re.split(pattern, text) # 过滤空内容并清理首尾空格 return [part.strip() for part in parts if part.strip()] # 测试特殊场景 sentence_1 = 'abc.io is a company that employs 10,000 people, half of them in greece.' print(split_sentences(sentence_1)) # 输出:['abc.io is a company that employs 10,000 people', 'half of them in greece'] # 测试原示例 sentence = 'i was born in germany (near Frankfurt, in the center of the country) but i live in france. what about you? i know you have a similar story.' print(split_sentences(sentence)) # 输出:['i was born in germany (near Frankfurt, in the center of the country) but i live in france', 'what about you', 'i know you have a similar story']
方案二:直接匹配句子片段(re.findall)
改用re.findall直接匹配符合要求的句子片段,避免拆分逻辑带来的边界问题,可读性更强:
import re def split_sentences(text): # 匹配规则: # 允许包含任意字符,除了句子终结标点, # 同时放行域名点(.后跟字母)、数字千分位逗号(,后跟数字) pattern = r'(?:[^.!?,]|\.(?=[a-zA-Z])|,(?=\d))+' parts = re.findall(pattern, text) # 清理首尾空格并过滤空内容 return [part.strip() for part in parts if part.strip()] # 测试特殊场景 sentence_1 = 'abc.io is a company that employs 10,000 people, half of them in greece.' print(split_sentences(sentence_1)) # 输出:['abc.io is a company that employs 10,000 people', 'half of them in greece']
扩展说明
如果需要处理更多特殊场景(如邮箱xxx@yyy.com、缩写U.S.A.),只需在正则中添加对应的放行规则即可。例如处理邮箱,可在匹配规则中加入@\w+\.来保留邮箱内的点。
内容的提问来源于stack exchange,提问作者LJG
相关产品推荐
相关产品推荐

