Python re模块负前瞻失效:匹配结果意外包含目标字符串
问题原因与解决方案
负前瞻失效的核心原因
你之前的负前瞻写法(?!des)逻辑有误:它仅检查匹配片段的末尾位置之后是否不是des,而非确保商家名之后不会紧跟des。比如在CHASE CREDIT CRD DES AUTOPAY中,若正则是([A-Z\s]+)(?!des),会匹配到CHASE CREDIT CRD DES——因为这个片段的末尾后面是 AUTOPAY,不是des,符合(?!des)的条件,但实际上该片段包含了des,完全违背需求。
正确正则写法与互补列表生成
1. 匹配规则定义
假设你的商家名由字母、空格、缩写(如CRD)组成,且“被des跟随”指商家名后紧跟独立的DES单词(不区分大小写):
- 匹配被DES跟随的商家名:用正前瞻锁定DES前的内容,非贪婪匹配避免过度截取
- 匹配不被DES跟随的商家名:用负前瞻排除后续紧跟DES的情况,同时兼容字符串结尾
2. 代码实现
import re import pandas as pd # 示例DataFrame(替换为你的实际数据) df = pd.DataFrame({ 'transaction': [ 'CHASE CREDIT CRD DES AUTOPAY', 'AMAZON.COM PAYMENT', 'APPLE STORE DES BILL', 'STARBUCKS COFFEE' ] }) # 编译正则(re.IGNORECASE兼容大小写) regex_followed = re.compile(r'([A-Z\s]+?)(?=\s+DES\b)', re.IGNORECASE) regex_not_followed = re.compile(r'([A-Z\s]+?)(?=\s+(?!DES\b)|$)', re.IGNORECASE) # 提取两类商家名,确保无交集 df['followed_by_des'] = df['transaction'].apply( lambda x: regex_followed.search(x).group(1).strip() if regex_followed.search(x) else None ) df['not_followed_by_des'] = df['transaction'].apply( lambda x: regex_not_followed.search(x).group(1).strip() if (regex_not_followed.search(x) and not regex_followed.search(x)) else None ) # 生成互补列表 followed_list = df['followed_by_des'].dropna().tolist() not_followed_list = df['not_followed_by_des'].dropna().tolist()
3. 关键逻辑说明
regex_followed:用(?=\s+DES\b)正前瞻,确保匹配的内容后面紧跟独立的DES单词;+?非贪婪匹配避免把DES也包含进去regex_not_followed:用(?=\s+(?!DES\b)|$)负前瞻,确保匹配的内容后面要么是字符串结尾,要么是后续单词不是DES- 提取
not_followed_by_des时,额外排除已被followed_by_des匹配的行,严格保证两个列表无交集
内容的提问来源于stack exchange,提问作者etw
相关产品推荐
相关产品推荐

