9

我不明白为什么'(\s*)+'会出错'nothing to repeat'。同时'(\s?)+'进行得很好。

我发现这个问题已经有一段时间了(例如正则表达式错误 - 无需重复),但我仍然在 Python 3.3.1 中看到它。

所以我想知道这种行为是否有合理的解释。

实际上我想匹配一行重复的单词或数字,例如:

'foo foo foo foo'

我想出了这个:

'(\w+)\s+(\1\s*)+'

它失败是因为第二组:(\1\s*)+ 在大多数情况下,我可能不会在单词之间留超过 1 个空格,所以(\1\s?)+会起作用。出于实际目的,此选项也应该有效(\1\s{0,1000})+

更新: 我想我应该补充一点,我只在 python 中看到了这个问题。在 perl 中它可以工作:

`('foo foo foo foo' =~ /(\w+)\s+(\1\s*)+/) `

不确定它是否等效,但 vim 也可以:

`\(\<\w\+\>\)\_s\+\(\1\_s*\)\+`

更新 2: 我找到了另一个用于 python 的正则表达式实现,据说它有一天会取代当前的 re。我检查了上述有问题的情况并没有发生错误。该模块必须单独安装。可以在这里下载或者通过pypi下载

4

2 回答 2

6

python遇到的问题主要是链接帖子中提出的空问题。如果您要拥有至少一个角色,我建议您改用:

(\s+)+

(\s*)+就是说,如果您要求的想法+需要存在而*实际上并不存在,那么它也没有任何意义。匹配也不是很有意义?,但是您可以通过说它是可选匹配来在心理上解决它,这意味着如果它没有找到它会继续前进,而不是*将任何内容解释为匹配的模式。

但是,如果您真的想检查 Python 的问题是什么,我建议您使用范围。例如,我通过使用以下两个示例得出结论:

re.compile("(\s{1,})+")

这很好

re.compile("(\s{0,})+")

以同样的方式失败。

至少这意味着它不是 Python 中的“错误”。这是一个有意识的设计决策,它作用于概念上落入同一个坑的每个正则表达式模式。我的猜测(在几个不同的环境中检查)是肯定(\s{0,})+会失败,因为它显式地重复了一个潜在的空元素。

但是,似乎许多环境都使用*来指示匹配是可选的,而 python 并没有遵循这种选择。在许多情况下这很有意义,但偶尔会导致奇怪的行为。我认为 Guido 在这里做出了正确的选择,因为空间存在不一致意味着您违反了抽水引理,并且您的模式不再是上下文无关的。

在这种情况下,它可能无关紧要,但这意味着该正则表达式中不可避免地存在无法解决的歧义。

所以你有一个问题,然后你选择使用正则表达式来解决这个问题。现在你有两个问题,C'est la vie。

于 2013-07-10T20:34:41.693 回答
0

Slater 对这个问题给出了一个很好的概述,但我只想补充一点,如果你考虑一下,理论上它会在它遇到的第一个空白空间上匹配无限数量的空白空间。如果您可以编译该表达式,那么应用它很可能会在看到第一个字符之前导致无限循环。因此,它不仅不是错误,而且是一件好事。

于 2013-07-10T20:42:32.103 回答