提问者:小点点

preg_match in循环返回不可能的结果


我肯定我错过了什么。我知道的足够危险。

在我的php代码中,我使用file_get_contents()将文件放入变量中。

然后我循环遍历一个数组,并使用preg_match多次搜索同一个变量。该文件是一个以制表符分隔的txt文件。它在中间做800次,但一次是随机的,它做了一些非常奇怪的事情。

$current = file_get_contents($file);    
foreach($blahs as $blah){
$image = 'somefile.jpg';
$pattern = '/https:\/\/www\.example\.com\/media(.*)\/' . preg_quote($image) . '/';
preg_match($pattern, $current, $matches);
echo $matches[0];
}

出于某种原因,有一次它会在两个URL之间切换一个选项卡。当我查看txt文件时,首先列出我要查找的图像,然后是第二个图像,但echo$matches[0]以相反的顺序返回它。它不存在,就像echo$匹配[0]返回它一样。这就像搜索字符串“一两”,而$matches返回“二十一”。


共1个答案

匿名用户

正则表达式引擎正试图帮你一个忙并捕获最长的匹配。两个URL之间的\t选项卡由匹配(点/任意字符)。

演示:(链接)

$blah='test case: https://www.example.com/media/foo/bar.jpg  https://www.example.com/media/cat/fish.jpg some text';
$image = 'fish.jpg';
$your_pattern = '/https:\/\/www\.example\.com\/media(.*)\/'.preg_quote($image).'/';
echo preg_match($your_pattern,$blah,$matches)?$matches[0]:'fail';

echo "\n----\n";

$my_pattern='~https://www\.example\.com/media(?:[^/\s]*/)+'.preg_quote($image).'~';
echo preg_match($my_pattern,$blah,$out)?$out[0]:'fail';

输出:

https://www.example.com/media/foo/bar.jpg  https://www.example.com/media/cat/fish.jpg
----
https://www.example.com/media/cat/fish.jpg

结晶。。。

test case: https://www.example.com/media/foo/bar.jpg  https://www.example.com/media/cat/fish.jpg some text
// your (.*) is matching ---------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我建议的模式(我可能能够细化的模式,如果您提供的样本字符串)使用(?:[^/\s]*/) 而不是(.*)

我的非捕获组如下所示:

(?:       #start non-capturing group
[^/\s]*   #greedily match zero or more non-slash, non-whitespace characters
/         #match a slash
)         #end non-capturing group
+         #allow the group to repeat one or more times

*注1:您可以在我使用\t的地方使用\s如果您想更直白一些,我使用的是\s,因为有效的url无论如何都不应该包含空格。您可以在项目中进行此调整,而不会损失任何准确性。

*注意2:注意,我将模式分隔符更改为~,这样就不需要在模式内转义/