如何使含捕获组的Regex仅匹配未被((NOUN))包裹的文本
解决正则误替换((NOUN)包裹区域内内容的问题
现有Python正则代码会错误地对((NOUN)和))包裹区域内的文本执行替换,比如将((NOUN)(del auto rojizo, dentro de algo grande y completamente veloz))修改为((NOUN)(del auto rojizo, ((PL_ADVB)dentro de algo grande y completamente veloz))),不符合预期。我们需要调整正则逻辑,仅在该包裹区域外进行捕获替换,最终得到正确的输出结果。
修改后的完整代码
import re input_text = "((PL_ADVB)alrededor ((NOUN)(del auto rojizo, dentro de algo grande y completamente veloz)). Luego dentro del baúl rápidamente abajo de una caja por sobre ello vimos una caña." #example input place_reference = r"(?i:[\w,;.]\s*)+?" list_all_adverbs_of_place = ["adentro", "dentro", "al rededor", "alrededor", "abajo", "hacía", "hacia", "por sobre", "sobre"] list_limiting_elements = list_all_adverbs_of_place + ["vimos", "hemos visto", "encontramos", "hemos encontrado", "rápidamente", "rapidamente", "intensamente", "durante", "luego", "ahora", ".", ":", ";", ",", "(", ")", "[", "]", "¿", "?", "¡", "!", "&", "="] # 构建正则:要么匹配((NOUN)...))块,要么匹配目标地点副词模式 noun_block_pattern = r"\(\(NOUN\)\(.*?\)\)" target_pattern = r"(?:(?<=\s)|^)({})(\s+{})(?=\s*({}))".format( '|'.join(re.escape(x) for x in list_all_adverbs_of_place), place_reference, '|'.join(re.escape(x) for x in list_limiting_elements) ) pattern = re.compile(rf"({noun_block_pattern})|({target_pattern})", flags=re.IGNORECASE | re.DOTALL) def replace_match(match): if match.group(1): # 匹配到NOUN包裹块,直接返回原内容 return match.group(1) else: # 匹配到目标模式,执行原替换逻辑 advb = match.group(3) ref = match.group(4) follow = match.group(5) return f"((PL_ADVB){advb}{ref}){follow}" if ref else f"((PL_ADVB){advb} NO_DATA){follow}" input_text = re.sub(pattern, replace_match, input_text) print(repr(input_text))
关键改动说明
- 正则分支设计:将正则拆分为两个分支,第一个分支精准匹配
((NOUN)(...))格式的包裹块(使用re.DOTALL让.匹配换行符,确保跨行也能正确识别);第二个分支保留原有的地点副词匹配逻辑。 - 替换回调函数:在
re.sub中使用自定义函数,判断匹配结果:如果是NOUN包裹块则直接返回原内容,不做修改;如果是目标地点副词模式,则按照原逻辑添加((PL_ADVB))标记。 - 调整捕获组顺序:因为新增了NOUN块的捕获组,所以需要调整后续捕获组的索引,确保替换时取到正确的内容。
执行上述代码后,将得到预期输出:
'((PL_ADVB)alrededor ((NOUN)(del auto rojizo, dentro de algo grande y completamente veloz)). Luego ((PL_ADVB)dentro del baúl) rápidamente ((PL_ADVB)abajo de una caja) ((PL_ADVB)por sobre ello) vimos una caña.'
内容的提问来源于stack exchange,提问作者Matt095
相关产品推荐
相关产品推荐

