如何解决正则捕获组重叠问题以正确捕获目标子串?
问题:优化西班牙语名词修饰结构的正则匹配
当前需识别西班牙语中限定词+名词+可选修饰连接词+多个并列修饰语的结构,原代码仅将sentence_capture_pattern中的\s+替换为\s*才能实现部分匹配,推测为捕获组重叠导致。需优化正则逻辑,确保正确匹配目标结构,并将匹配内容替换为((NOUN)'匹配内容')。
原代码
import re input_text = "En esta alejada ciudad por la tarde circulan muchos camiones con aquellos acoplados rojos, grandes y bastante pesados, llevándolos por esos trayectos bastante empedrados, polvorientos, y un tanto arenosos. Y incluso bastante desde lejos ya se les puede ver." #example string list_verbs_in_this_input = ["serías", "serían", "sería", "ser", "es", "llevándoles", "llevándole", "llevándolos", "llevándolo", "circularías", "circularía", "circulando", "circulan", "circula", "consiste", "consistían", "consistía", "consistió", "visualizar", "ver", "empolvarle", "empolvar", "verías", "vería", "vieron", "vió", "vio", "ver", "podrías" , "podría", "puede"] exclude = rf"(?!\b(?:{'|'.join(list_verbs_in_this_input)})\b)" direct_subject_modifiers, noun_pattern = exclude + r"\w+" , exclude + r"\w+" modifier_connectors = r"(?:(?:a[úu]n|todav[íi]a|incluso)\s+|)\s*(?:de|)\s*(?:gran|bastante\s*(?:m[áa]s|menos|)|(?:un\s*(?:tanto|poco)|)\s*(?:m[áa]s|menos)|)" #its occurrence is optional #enumeration_of_noun_modifiers = direct_subject_modifiers + "(?:" + modifier_connectors + direct_subject_modifiers + "){2,}" enumeration_of_noun_modifiers = r"(?:" + "(?:(?:,\s*|)y|,)\s*" + modifier_connectors + r"\s*" + direct_subject_modifiers + r"\s*" + r")*" #sentence_capture_pattern = r"(?:aquellas|aquellos|aquella|aquel|los|las|el|la|esos|esas|este|ese|otros|otras|otro|otra)\s+" + noun_pattern + r"\s+" + enumeration_of_noun_modifiers sentence_capture_pattern = r"(?:aquellas|aquellos|aquella|aquel|los|las|el|la|esos|esas|este|ese|otros|otras|otro|otra)\s+" + noun_pattern + r"\s+" + modifier_connectors + r"\s+" + direct_subject_modifiers + r"\s+" + r"(?:" + enumeration_of_noun_modifiers + r"|)" input_text = re.sub(sentence_capture_pattern, r"((NOUN)'\g<0>')", input_text, flags=re.I|re.U) print(repr(input_text)) # --> output
优化后的代码及说明
import re input_text = "En esta alejada ciudad por la tarde circulan muchos camiones con aquellos acoplados rojos, grandes y bastante pesados, llevándolos por esos trayectos bastante empedrados, polvorientos, y un tanto arenosos. Y incluso bastante desde lejos ya se les puede ver." # 需要排除的动词列表 excluded_verbs = ["serías", "serían", "sería", "ser", "es", "llevándoles", "llevándole", "llevándolos", "llevándolo", "circularías", "circularía", "circulando", "circulan", "circula", "consiste", "consistían", "consistía", "consistió", "visualizar", "ver", "empolvarle", "empolvar", "verías", "vería", "vieron", "vió", "ver", "podrías" , "podría", "puede"] # 优化排除逻辑:匹配非动词的完整单词,避免逐字符检查 exclude_pattern = rf"\b(?!(?:{'|'.join(excluded_verbs)})\b)\w+\b" noun_pattern = exclude_pattern modifier_pattern = exclude_pattern # 简化修饰连接词逻辑:用?替代冗余的|,明确可选结构 modifier_connectors = r"(?:(?:a[úu]n|todav[íi]a|incluso)\s*)?\s*(?:de\s*)?(?:gran|bastante\s*(?:m[áa]s|menos)?|(?:un\s*(?:tanto|poco)?)\s*(?:m[áa]s|menos))?" # 重构并列修饰语枚举:统一连接逻辑,避免重叠匹配 enumerated_modifiers = r"(?:\s*(?:,|y)\s*" + modifier_connectors + r"\s*" + modifier_pattern + r")*" # 完整捕获模式:锚定单词边界,逻辑连贯的结构匹配 sentence_capture_pattern = r"\b(?:aquell[ao]s?|los|las|el|la|es[ao]s?|est[ae]|ot[ra]s?)\s+" + noun_pattern + r"\s+" + modifier_connectors + r"\s*" + modifier_pattern + enumerated_modifiers + r"\b" # 执行替换 input_text = re.sub(sentence_capture_pattern, r"((NOUN)'\g<0>')", input_text, flags=re.I|re.U) print(repr(input_text))
核心优化点
- 排除逻辑优化:将原逐字符的负前瞻改为单词级负前瞻
\b(?!...)\w+\b,避免匹配错误和性能损耗 - 连接词简化:用
?替代多余的|,明确可选结构的逻辑,降低正则复杂度 - 枚举结构重构:统一并列修饰语的连接逻辑,避免原结构的重叠匹配风险
- 边界锚定:添加
\b确保匹配完整的名词修饰结构,防止部分单词匹配
预期输出
"En esta alejada ciudad por la tarde circulan muchos camiones con ((NOUN)'aquellos acoplados rojos, grandes y bastante pesados'), llevándolos por ((NOUN)'esos trayectos bastante empedrados, polvorientos, y un tanto arenosos'). Y incluso bastante desde lejos ya se les puede ver."
内容的提问来源于stack exchange,提问作者Matt095
相关产品推荐
相关产品推荐

