正则表达式的前瞻匹配

6

我正在使用正则表达式来查找:

test:?

跟随任何字符直到它遇到下一个:

test:?

现在当我运行我写的这个正则表达式时:
((?:test:\?)(.*)(?!test:\?))

在这段文字中:

test:?foo2=bar2&baz2=foo2test:?foo=bar&baz=footest:?foo2=bar2&baz2=foo2

我期望得到:

test:?foo2=bar2&baz2=foo2

test:?foo=bar&baz=foo

test:?foo2=bar2&baz2=foo2

但实际上它匹配了所有内容。有经验的正则表达式用户能否告诉我哪里出错了?我以前用过正则表达式进行模式匹配,但这是我第一次使用lookaround/lookahead。
提前感谢任何帮助、提示和指导 :-)

你只是想在 test:? 上进行分割吗?如果是的话,你的环境将提供一种无需正则表达式即可完成的方法。 - Chris Morgan
4个回答

5
我想你可以尝试一下贪心版本。
(扩展)

(test:\? (?: (?!test:\?)[\s\S])* )


谢谢。这个完美地运行了,我也学到了更多的语法。 - james

2
下面是Perl程序:
#! /usr/bin/env perl

use strict;
use warnings;

$_ = "test:?foo2=bar2&baz2=foo2test:?foo=bar&baz=footest:?foo2=bar2&baz2=foo2";

while (/(test:\?  .*?) (?= test:\? | $)/gx) {
  print "[$1]\n";
}

从您的问题中产生所需的输出,加上用于强调的括号。

[测试:?foo2=bar2&baz2=foo2]
[测试:?foo=bar&baz=foo]
[测试:?foo2=bar2&baz2=foo2]

请记住,正则表达式量词是贪婪的,希望尽可能多地吞噬而不破坏匹配。每个子段都要尽快终止,这意味着使用 .*? 语义。

每个子段都以另一个 test:? 或字符串结尾终止,我们使用 (?=...) 零宽度前瞻包装在 | 中进行替代。

上面代码中的模式使用了 Perl 的 /x 正则表达式开关,以提高可读性。根据您使用的语言和库,您可能需要删除额外的空格。


我在正则表达式测试器中使用了您的语法,但匹配仍然给出了一个包含两个“test:?”字符串的字符串。我正在使用Java,所以我认为这可能与语法有关?(我已经删除了空格进行测试)。感谢您的帮助,我学到了更多。 - james

0

三个问题:

  • (?!) 是负向前瞻断言。您需要使用 (?=),要求接下来的内容是 test:?

  • .* 是贪婪模式;您需要它为非贪婪模式,以便只获取第一个块。

  • 您还想获取最后一个块,因此您需要在结尾处同时匹配 $

最终结果:

(?:test:\?)(.*?)(?=test:\?|$)

我还删除了外部组,因为我认为它没有意义。我所知道的所有正则表达式引擎都允许您访问第0组作为完整匹配,或者以某种其他方式访问(尽管在查找所有匹配项时可能不是这样)。如果需要,您可以将其放回。

(这适用于PCRE;我不确定它是否适用于POSIX正则表达式,因为我不习惯使用它们。)

如果您只想在test:?上拆分,则正则表达式是错误的工具。使用您的语言内置的支持来拆分字符串。

Python:

>>> re.findall('(?:test:\?)(.*?)(?=test:\?|$)',
... 'test:?foo2=bar2&baz2=foo2test:?foo=bar&baz=footest:?foo2=bar2&baz2=foo2')
['foo2=bar2&baz2=foo2', 'foo=bar&baz=foo', 'foo2=bar2&baz2=foo2']

-1

你可能需要使用((?:test:\?)(.*?)(?=test:\?)),但是你没有告诉我们你使用的是什么语言来驱动正则表达式。

.*?匹配尽可能少的字符,而不会阻止整个字符串匹配,而.*则匹配尽可能多的字符(贪婪)。

根据你使用的编程语言,你可能需要先进行匹配,然后再截取字符串,再进行匹配,或者调用一些特定于语言的match_all类型函数。

顺便说一句,你不需要使用前瞻来锚定正则表达式(你可以直接匹配要搜索的模式),所以在你的情况下,这样做就可以了:

test:[?](.*?)test:[?]

1
如果你要采用这种方法,那么你需要将?!更改为?= - ruakh
1
-1,需要前瞻。如果没有它,因为“test:”已经被消耗掉,每个其他所需的匹配都不会匹配。 - Qtax

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接