5

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

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

4 回答 4

4

我想你可以探索一个贪婪的版本。
(扩展)

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

于 2012-02-25T01:46:50.017 回答
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正则表达式开关以提高可读性。根据您使用的语言和库,您可能需要删除额外的空格。

于 2012-02-25T01:09:19.247 回答
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']
于 2012-02-25T00:52:43.970 回答
-1

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

在不阻止整个字符串匹配的情况下,.*?匹配尽可能少.*的字符,其中匹配尽可能多(贪婪)。

同样,根据您使用的语言来执行此操作,您可能需要匹配,然后切分字符串,然后再次匹配,或者调用一些特定于语言的 match_all 类型函数。

顺便说一句,您不需要使用前瞻来锚定正则表达式(您可以只匹配要搜索的模式),因此(很可能)在您的情况下会这样做:

test:[?](.*?)test:[?]
于 2012-02-25T00:48:32.620 回答