正则表达式前瞻

时间:2012-02-25 00:45:41

标签: regex regex-lookarounds

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

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

但它匹配一切。有更多正则表达式经验的人知道我哪里出错吗?我以前曾使用正则表达式进行模式匹配,但这是我第一次看到前瞻/未来的经历。

提前感谢任何帮助/提示/指示: - )

4 个答案:

答案 0 :(得分:4)

我想你可以探索一个贪婪的版本 (膨胀)

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

答案 1 :(得分: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";
}

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

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

请记住regex quantifiers are greedy,并希望尽可能地吞噬,而不会破坏比赛。每个子段尽快终止,这意味着.*?语义。

每个子细分都以另一个test:?或字符串结尾终止,我们通过(?=...)零宽度前瞻搜索|来寻找替代方案。

上面代码中的模式使用Perl’s /x regex switch来提高可读性。根据您使用的语言和库,您可能需要删除额外的空格。

答案 2 :(得分:0)

三个问题:

  • (?!)是一个负面的先行断言。您需要(?=),要求接下来的内容是test:?

  • .*贪婪;你希望它不贪婪,以便你只抓住第一块。

  • 你也想要最后一个块,所以你想在最后匹配$

最终结果:

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

我也删除了外部组,没有任何意义。我所知道的所有RE引擎都允许您将组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']

答案 3 :(得分:-1)

你可能想要((?:test:\?)(.*?)(?=test:\?)),虽然你还没有告诉我们你用什么语言来驱动正则表达式。

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

再次,根据您使用的语言,您可能需要匹配,然后切断字符串,然后再次匹配,或调用某些特定于语言的match_all类型函数。

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

test:[?](.*?)test:[?]
相关问题