如何让Python的负面外观不那么贪婪?

时间:2012-05-02 20:26:06

标签: python regex

我已阅读所有相关帖子并浏览互联网,但这真的打败了我。

我有一些包含日期的文字 我想捕捉日期,但如果它前面有某个短语,则不会。

一个简单的解决方案是为我的RegEx添加负面的lookbehind。

以下是一些例子(使用findall) 如果日期前面没有短语“as of”,我只想捕获日期。

  

19-2-11
  什么东西15-4-11
  例如29-5-11

这是我的正则表达式:

(?<!as of )(\d{1,2}-\d{1,2}-\d{2})

预期结果:

  

[ '19-2-11']
  ['15 -4-11' ]
  []

实际结果:

  

[ '19-2-11']
  ['15 -4-11' ]
  ['9-5-11']

请注意,9不是29.如果我在第一个模式上将\d{1,2}更改为\d{2}之类的内容:

bad regex for testing: (?<!as of )(\d{2}-\d{1,2}-\d{2})

然后我得到了预期的结果。当然这不好,因为我想匹配2位数天和单位数天。

显然我的负面观察是贪婪 - 比我的日期捕捉还要多,所以它从它那里偷了一个数字并且失败了。我已经尽力纠正了我能想到的贪婪,但我只是不知道要解决这个问题。

我希望我的日期捕捉与最大的贪婪相匹配,然后应用我的负面看法。这可能吗?我的问题似乎很好地利用了消极的外观,而不是过于复杂。我相信如果必须,我可以用另一种方式完成它,但我想学习如何做到这一点。

如何让Python的负面看上去不那么贪心?

3 个答案:

答案 0 :(得分:7)

这与贪婪毫无关系。贪婪不会改变正则表达式是否匹配 - 它只更改执行搜索的顺序。这里的问题是你的正则表达式需要更具体,以避免不必要的匹配。

要解决此问题,您可能需要在比赛开始之前使用单词边界:

(?<!as of )\b(\d{1,2}-\d{1,2}-\d{2})
#          ^^ add this

答案 1 :(得分:1)

原因不是因为看守是贪婪的。发生这种情况是因为正则表达式引擎尝试在每个位置匹配模式。

首先成功匹配such and such as of 29-5-11的短语(?<!as of ),但未匹配\d{1,2}

但随后引擎会将自己置于such and such as of !29-5-11位置(标有!)。但在这里它无法匹配(?<!as of )

它前进到下一个位置:such and such as of 2!9-5-11。成功匹配(?<!as of )然后\d{1,2}

的位置

如何避免它?

一般的解决方案是尽可能明确地制定模式

在这种情况下,我会在数字前加上必要的空格或字符串的开头。

(?<!as of)(?:^|\s+)(\d{1,2}-\d{1,2}-\d{2})

Mark Byers的解决方案也非常好。

我认为理解正则表达式引擎以这种方式运行并产生不必要结果的原因非常重要。

顺便说一下,如果有2个或更多的空格,我上面给出的解决方案不起作用。 它不起作用,因为第一个位置与such and such as of ! 29-5-11匹配上述模式。

可以做些什么来避免它?

不幸的是,Python正则表达式引擎中的后端不支持量词+*

我认为最简单的解决方案是确保(?:^|\s+)之前没有空格(假设所有空格在任何非空格文本之后直接被(?:^|\s+)消耗(如果文本为{ {1}},终止前进并回溯到下一个起始位置,在搜索文本的下一个位置再次开始搜索。)

as of

答案 2 :(得分:-1)

一个简单的解决方案是在使用正则表达式隔离日期之前扔掉所有匹配'截至'的行。