字符串上的正则表达式负向lookbehind

时间:2014-03-14 00:32:32

标签: php regex pcre

我似乎无法找到一种方法,如果字符串存在但是不能立即在另一个字符串之前,则不会返回匹配。

如果字符串立即在另一个字符串之前存在,我将无法返回匹配项。具有以下内容。

$string = 'Stackoverflow hello world foobar test php';

$regex = "~(Stackoverflow).*?(?<!(test\s))(php)~i";

if(preg_match_all($regex,$string,$match))
    print_r($match);

在这个例子中,如果我们有单词 Stackoverflow php ,我们想要返回一个匹配,但只有当单词 test 时(在 php 之前不存在空格字符。

这不会返回任何好的结果。

现在让我说要匹配 php ,但只有在 Stackoverflow php之间不存在 foobar 这个词时,我以为我可以做到以下几点。

$string = 'Stackoverflow hello world foobar test php';

$regex = "~(Stackoverflow).*?(?<!(foobar)).*?(php)~i";

if(preg_match_all($regex,$string,$match))
    print_r($match);

(我已将字符串背后的负面效果更改为(foobar),并添加。*?之后)

我还想说我不能总是知道 foobar php 之间会有什么词,有时候会有,有时只有200,但我确实有一些定位信息(在 Stackoverflow 之后和 php 之前)。

2 个答案:

答案 0 :(得分:1)

你的第二个正则表达式起作用是因为&#34; foobar&#34;可以作为一个.*?的一部分发生。具体来说,第一个.*?将匹配空字符串&#34;&#34;,第二个匹配&#34;你好世界foobar测试&#34;,确实没有&#34; foobar&#34;!

为了获得理想的结果,一种方法是查看每个角色并确保它不是&#34; f&#34;或者如果它是&#34; f&#34;这不是&#34; o&#34;或者如果它是&#34; f&#34;然后是&#34; o&#34;它不会跟随另一个&#34; o&#34;等等。

这将离开你:

$string = 'Stackoverflow hello world foobar test php';

$regex = "~(Stackoverflow)(?:[^f]|f[^o]|fo[^o]|foo[^b]|foob[^a]|fooba[^r])*?(php)~i";

if(preg_match_all($regex,$string,$match))
    print_r($match);

效果更新

我对我的建议进行了基准测试,并发现,虽然Perl没有显着差异,但他在PCRE中的速度提高了近50%。

答案 1 :(得分:1)

我会使用负向前瞻来确保字符串&foffar。* php&#39; stackoverflow&#39;之后不存在既然你想捕获php,我就把它放到一个捕获组中。类似的东西:

Stackoverflow(?:(?!foobar.*php).)*(php)

请注意,这导致在每个字符后检查