python中的re.search()进入无限循环

时间:2017-02-21 17:53:36

标签: python regex text-mining regular-language

我试图从文本文档中提取文件路径(Windows / Ubuntu,相对/绝对)。

使用下面的正则表达式代码检查单词是否是文件路径。

它适用于大多数情况,但对于一个案例失败,它进入无限循环。对此有何解释?

import re
path_regex = re.compile(r'^([\.]*)([/]+)(((?![<>:"/\\|?*]).)+((?<![ .])(\\|/))?)*$' , re.I)
text = '/var/lib/jenkins/jobs/abcd-deploy-test-environment-oneccc/workspace/../workspace/abcd-deploy-test-environment.sh'
path_regex.search(text)

2 个答案:

答案 0 :(得分:3)

确实存在问题 你已经叠加了与虚假量词混合的子表达式。

针对斜杠之间的必需部分进行了修改
使用此^([\.]*)([/]+)((?:[^<>:"/\\|?*.\r\n]|\.(?![\\/]))[\\/]?)*$

可以轻松修复此问题

我们的想法是看看你的防守措施 如果没有一个点,你可以允许前进或后退。

因此,您必须在排除类中包含 dot 和\和/
然后在单独的轮换中对它们进行限定。

如果你这样做,它将永远通过。

 ^ 
 ( [\.]* )                     # (1)
 ( [/]+ )                      # (2)
 (                             # (3 start)
      (?:                           # Group start (required between slashes)
           [^<>:"/\\|?*.\r\n]            # Any character, but exclude these
        |                              # or,
           \.                            # The dot, if not followed by forward or back slash
           (?! [\\/] )
      )                             # Group end
      [\\/]?                        # Optional forward or back shash
 )*                            # (3 end)
 $

答案 1 :(得分:2)

sln为您的问题提供了一个很好的解决方案,因此我将尝试解释问题是什么

欢迎来到catastrophic backtracking的欢乐。问题的核心在(((?![<>:"/\\|?*]).)+((?<![ .])(\\|/))?)*。 (现在我已经说过了,你所有的问题都解决了,对吗?很容易。)

假设你有点像我,并且在第一次有人说&#34;正则表达式回溯&#34;时眨了眨眼几次,我们可以使用较短的输入/path./来处理你的正则表达式。根据你的正则表达式,这是一个无效的路径,但让我们(有点)轻松地解决问题。

^([\.]*)([/]+)与前导/匹配。这很好。

为了便于阅读,我打算调用有问题的捕获组的前半部分((?![<>:"/\\|?*]).)+x+和下半部((?<![ .])(\\|/))?y?。整个小组是(x+y?)

匹配(x+y?)*$后,path./如何回溯?

  1. x+匹配path.
  2. y?匹配(匹配0次,由于?,这很好)
  3. (x+y?)现已匹配
  4. (x+y?)重复,但失败,因为它与/不匹配。因此,(x+y?)*已匹配path.
  5. $失败,因为它与/不匹配。
  6. 正则表达式引擎回溯:
    • (x+y?)*只能回溯到第一次迭代,因为它只有一次迭代。
    • 在该次迭代中,y?无法回溯,因为它匹配了0次。
    • x+回溯,仅匹配path而不是path.
  7. x+匹配path
  8. y?匹配
  9. (x+y?)现已匹配一次(path
  10. (x+y?)重复并再次匹配:
    • x+匹配.
    • y?匹配
  11. (x+y?)重复,但由于与/不匹配而失败。因此,(x+y?)*已匹配path.
  12. $失败,因为它与/不匹配。
  13. 正则表达式引擎回溯:
    • (x+y?)*只能回溯到第一次迭代,因为在第二次迭代x+只匹配一次而y?匹配0次。
    • 第一次迭代中的
    • y?匹配0次,因此无法回溯
    • x+可以回溯到仅匹配pat
  14. 希望您明白这一点,但(x+y?)匹配两次:path.;然后在下一个回溯中我们pat h .,然后是pa th.,依此类推。
  15. 引擎需要478步才能确定/path./与正则表达式不匹配。该有问题的捕获组中的每个附加角色都会通过 lot 增加回溯次数,并且在某一点之后,您的正则表达式实现只会放弃并放弃。 sln的解决方案只需49步。

    回溯引擎在回溯时的行为很难解释和掌握,特别是在限制为Markdown的情况下,因此我建议您通过a debugger运行正则表达式来查看正在发生的事情。< / p>