使用管道加入一组正则表达式时出现正则表达式模块错误

出于性能目的,我尝试使用管道将一组正则表达式转换为仅一个。

   self.regexes_token = [
                {'descricao':'site www.', 'regex': r'^www.(.+?)$'},
                {'descricao':'apenas pontuacao','regex':r'^[[:punct:]]+?$'},
                {'descricao':'palavra com sinal negativo', 'regex': r'^(-)(.*?)$', 'grupo': r'2'},
                {'descricao':'pronomes e títulos', 'regex': r'^(sra?|exm[º|°|o]|dr[a|ª]?|(v.)?ex.?(a|ª).?).??$'},
                {'descricao':'oab sigla', 'regex': r'^oab/[a-z]{2}$'},
                {'descricao':'termos irrelevantes', 'regex': r'^(s/n|e/ou|e-?mail|cep|rj|tel.?(/fax|efone)?|anos?|rua|cpf|www).?$'},
                {'descricao':'chassi (VIN)', 'regex': r'^[A-Za-z0-9]{1}[A-Za-z]{2}[A-Za-z0-9]{9}[d+]{5}$'},
                {'descricao':'data_br', 'regex': r'^(?:(?:31(/|-|.)(?:0?[13578]|1[02]))1|(?:(?:29|30)(/|-|.)(?:0?[1,3-9]|1[0-2])2))(?:(?:1[6-9]|[2-9]d)?d{2})$|^(?:29(/|-|.)0?23(?:(?:(?:1[6-9]|[2-9]d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))|(?:0?[1-9]|1d|2[0-8])(/|-|.)(?:(?:0?[1-9])|(?:1[0-2]))4(?:(?:1[6-9]|[2-9]d)?d{2})$'},
                {'descricao':'um char e ponto', 'regex': r'^w[[:punct:]]$'},
                {'descricao':'rg','regex': r'^d{2}.d{3}.d{3}-d(/.*)?'},
                {'descricao':'unidades de medidas', 'regex': r'^(d{1,2},?x?)+(cm|m(l|²|2|m)?|k(g|m))$'},
                {'descricao':'zero seguido de qualquer coisa', 'regex': r'^0(.*)$'},
                {'descricao':'::punct:: seguido de qualquer coisa','regex':r'^[[:punct:]](.+?)$'},
                {'descricao':'telefone avulso', 'regex': r'^d{4,5}-d{4}$'},
                {'descricao':'ano', 'regex': r'b(19|20)d{2}.?b'},
                {'descricao':'contém char especial', 'regex': r'^.*?(~|^|¿|¡|>|<|»|#|£|?|»|·|#|*|=|+|¥|€|||µ|®)+.*?$'}
            ]
            
            
            self.regexes_token_union = r'('+'|'.join([d['regex'] for d in self.regexes_token])+r')'
            print(self.regexes_token_union)

遵循正则表达式:

(^www.(.+?)$|^[[:punct:]]+?$|^(-)(.*?)$|^(sra?|exm[º|°|o]|dr[a|ª]?|(v.)?ex.?(a|ª).?).??$|^oab/[a-z]{2}$|^(s/n|e/ou|e-?mail|cep|rj|tel.?(/fax|efone)?|anos?|rua|cpf|www).?$|^[A-Za-z0-9]{1}[A-Za-z]{2}[A-Za-z0-9]{9}[d+]{5}$|^(?:(?:31(/|-|.)(?:0?[13578]|1[02]))1|(?:(?:29|30)(/|-|.)(?:0?[1,3-9]|1[0-2])2))(?:(?:1[6-9]|[2-9]d)?d{2})$|^(?:29(/|-|.)0?23(?:(?:(?:1[6-9]|[2-9]d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))|(?:0?[1-9]|1d|2[0-8])(/|-|.)(?:(?:0?[1-9])|(?:1[0-2]))4(?:(?:1[6-9]|[2-9]d)?d{2})$|^w[[:punct:]]$|^d{2}.d{3}.d{3}-d(/.*)?|^(d{1,2},?x?)+(cm|m(l|²|2|m)?|k(g|m))$|^0(.*)$|^[[:punct:]](.+?)$|^d{4,5}-d{4}$|b(19|20)d{2}.?b|^.*?(~|^|¿|¡|>|<|»|#|£|?|»|·|#|*|=|+|¥|€|||µ|®)+.*?$)

但是当我尝试运行(编译)时,python 的正则表达式模块(不是重新)出现错误:

regex._regex_core.error: cannot refer to an open group at position 272

我已经使用记事本++来查看“col”位置,但即使如此我也无法检测到这是哪个打开的组

“令人困惑的事情”是,当我在循环中运行每个正则表达式时,它运行良好(但性能不佳)

那么,我该如何解决这个问题?

回答

这里的基本错误是,当您将正则表达式与 组合在一起时|,组运算符2将不会引用试图引用它的表达式中的第二个组而是引用组合正则表达式中第二个带括号的组。

部分解决方法是在任何地方都使用非分组括号,除非您确实需要引用组。更好的解决方法是在需要的地方定义命名组,这样您就可以通过名称而不是编号来引用它们。

实际的错误消息试图说在

r'^(?:(?:31(/|-|.)(?:0?[13578]|1[02]))1...
r'^(?:(?:31(/|-|.)(?:0?[13578]|1[02]))1...

您不能使用,1因为以第一个左括号开头的组尚未定义,因为我们还没有看到它的右括号。整个第一组是您开始时r'(' + '|'.join(...) + r')'最少的组,您必须对其重新编号以匹配组合正则表达式的编号 - 但同样,这几乎无法维护,并且易于使用命名组避免(至少在某一点上) ;如果您有很多命名组,跟踪名称冲突等也会成为一个问题)。

可能您正在尝试引用捕获的日期分隔符?如果是这样,请尝试

r'^(?:(?:31(?P<sep>[-/.])(?:0?[13578]|1[02]))(?P=sep)...

我还通过使用字符类简化了捕获表达式。

切线地,不需要反斜杠斜杠——斜杠根本不是正则表达式元字符,所以它只是匹配自己。另请注意,在字符类中,您只有一个字符列表,因此不应将它们分隔开|(当然,|如果您想匹配文字|,则包括一次,但在您的示例中似乎并非如此)。

这是对您的定义的非常机械的重构,所有分组括号替换为非分组括号,并用命名组替换组,我希望能够正确猜测组应该匹配的内容,以及纠正与以下内容相关的简单初学者错误斜线和字符类。还有一个是多余的{1}——很明显,一个字符的单个实例已经与自身完全匹配,您不必拼写出其中存在一个。(还想知道是否[1,3-9]应该是[13-9]?)

实际上不需要在联合表达式周围使用括号;他们不添加任何东西。

还要注意如何我换成'grupo': r'2''grupo': 'palavra'后也命名相应的组-你显然需要适应它试图使用该组通过,而不是拔出命名组的代码groupdict

在单个代码块中嵌入像这样的长而复杂的正则表达式真的无法维护。我没有尝试进一步重构代码,因为我没有假装理解它;但作为开始,您可能想要拆分庞大的正则表达式并将其拆分为多行,例如

                {'descricao':'data_br',
                 'regex': r'(?:(?:31(?P<sep>/|-|.)(?:0?[13578]|1[02]))(?P=sep)|'
                          r'(?:(?:29|30)(?P<sep2>/|-|.)(?:0?[1,3-9]|1[0-2])(?P=sep2)))(?:(?:1[6-9]|[2-9]d)?d{2})$|'
                          r'^(?:29(?P<sep3>/|-|.)0?2(?P=sep3)(?:(?:(?:1[6-9]|[2-9]d)?(?:0[48]|[2468][048]|[13579][26])|'
                          r'(?:(?:16|[2468][048]|[3579][26])00))))|(?:0?[1-9]|1d|2[0-8])(?P<sep4>/|-|.)'
                          r'(?:(?:0?[1-9])|(?:1[0-2]))(?P=sep4)(?:(?:1[6-9]|[2-9]d)?d{2})$'
                },

更好的是,使用re.X标志并将正则表达式写在带有嵌入注释的多行中。


以上是使用管道加入一组正则表达式时出现正则表达式模块错误的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>