有什么方法可以在perl RE中处理。* as。{0,1024}?

时间:2011-12-15 09:15:32

标签: regex perl optimization

我们允许一些用户提供的RE用于过滤电子邮件。早期我们在与任意大型电子邮件进行匹配时,会遇到包含.*的RE的一些性能问题。我们在用户提供的RE上找到了s/\*/{0,1024}/的简单解决方案。但是,这不是一个完美的解决方案,因为它会破坏以下模式:

/[*]/

而不是想出一些复杂的方法来解释用户提供的RE输入的每个可能的突变,我想限制perl对*+字符的解释最大长度为1024个字符。

有没有办法做到这一点?

4 个答案:

答案 0 :(得分:5)

这并不能真正回答您的问题,但您应该了解用户提供的正则表达式的其他问题,例如请参阅此summary at OWASP。根据您的具体情况,编写或查找自定义简单模式匹配库可能更好?

答案 1 :(得分:4)

<强>更新

在量词之前添加了(?<!\\),因为转义的* +不应该匹配。如果有\\*(匹配\ 0次或更多次),则替换仍然会失败。

这将是一个改进

s/(?<!\\)\*(?!(?<!\\)[^[]*?(?<!\\)\])/{0,1024}/
s/(?<!\\)\+(?!(?<!\\)[^[]*?(?<!\\)\])/{1,1024}/

here on Regexr

这意味着匹配[*+],但前提是前面没有关闭],之前没有[。在方括号前面不允许\ (?<!\\)部分)

(?! ... )是一个负面的预测

(?<! ... )是一个负面的背后隐藏

有关详细信息,请参阅perlretut

更新2包括占有量词

s/(?<!(?<!\\)[\\+*?])\+(?!(?<!\\)[^[]*?(?<!\\)\])/{1,1024}/   # for +
s/(?<!\\)\*(?!(?<!\\)[^[]*?(?<!\\)\])/{0,1024}/    # for *

here on Regexr

似乎正在发挥作用,但它现在变得越来越复杂了!

答案 2 :(得分:4)

使用Regexp::Parser获取树并根据需要修改正则表达式,或者为Regexp::English提供GUI界面

答案 3 :(得分:1)

你的意思是除了修补源码之外?

  1. 您可以在较短的块中分解输入文本并仅匹配那些。但话说回来,你不会匹配“线”休息。
  2. 你可以打破正则表达式,只搜索它的第一个字符,加载接下来的1024个字符的文本,然后匹配整个正则表达式(显然,这与正则表达式一起使用。)
  3. 找到正则表达式的第一个不是。* +()\的字符,找到它,在之前和之后加载1024个字符,然后在此字符串上匹配整个正则表达式。 (复杂和修剪奇怪的不可预见的正则表达式中的错误)