我似乎无法找到一种方法,如果字符串存在但是不能立即在另一个字符串之前,则不会返回匹配。
如果字符串立即在另一个字符串之前存在,我将无法返回匹配项。具有以下内容。
$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 之前)。
答案 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)
请注意,这导致在每个字符后检查