Python正则无(?J)修饰符时,实现同名捕获组跨模式捕获
Python正则:从两种序列模式中捕获同一命名组内容
问题场景
需要匹配以下两种格式的字符串,捕获其中的CAPTUREME到同一个命名捕获组cap中:
测试字符串:
abc-CAPTUREME-xyz-abcdef abc-xyz-CAPTUREME-abcdef
期望输出:
CAPTUREME CAPTUREME
最初尝试的正则因Python不允许重复命名组报错,且无法直接套用PCRE的(?J)修饰符。
解决方案
方案一:兼容Python 3.10以下版本
由于旧版本Python不支持重复命名捕获组,可定义两个不同命名组,提取时取非空值:
正则表达式
r'abc-(xyz-(?P<cap1>\w+)|(?P<cap2>\w+)-xyz)-abcdef'
使用示例
import re pattern = r'abc-(xyz-(?P<cap1>\w+)|(?P<cap2>\w+)-xyz)-abcdef' test_strings = [ 'abc-CAPTUREME-xyz-abcdef', 'abc-xyz-CAPTUREME-abcdef' ] for s in test_strings: match = re.fullmatch(pattern, s) if match: # 取非空的捕获组结果 result = match.group('cap1') or match.group('cap2') print(result)
输出
CAPTUREME CAPTUREME
方案二:Python 3.10+版本(推荐)
Python 3.10及以上版本允许在互斥分支中重复使用同一命名组,直接使用你最初的正则即可:
正则表达式
r'abc-(xyz-(?P<cap>\w+)|(?P<cap>\w+)-xyz)-abcdef'
使用示例
import re pattern = r'abc-(xyz-(?P<cap>\w+)|(?P<cap>\w+)-xyz)-abcdef' test_strings = [ 'abc-CAPTUREME-xyz-abcdef', 'abc-xyz-CAPTUREME-abcdef' ] for s in test_strings: match = re.fullmatch(pattern, s) if match: print(match.group('cap'))
输出
CAPTUREME CAPTUREME
方案三:环视定位写法(Python 3.10+)
通过调整分支结构,用非捕获组包裹前缀/后缀,同样实现同一命名组捕获:
r'abc-(?:(?P<cap>\w+)-xyz|xyz-(?P<cap>\w+))-abcdef'
使用方式和方案二完全一致,仅正则写法略有不同。
内容的提问来源于stack exchange,提问作者David Parks
相关产品推荐
相关产品推荐

