【问题标题】:preg_match in loop returning impossible results循环中的 preg_match 返回不可能的结果
【发布时间】:2018-02-26 22:59:54
【问题描述】:

我确定我错过了一些东西。我只知道够危险。

在我的 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 文件时,首先列出了我要查找的图像,然后是第二个 iamge,但 echo $matches[0] 以相反的顺序返回它。它不像 echo $matches[0] 返回它那样存在。就像您搜索字符串“一二”并且 $matches 返回“二一”一样。

【问题讨论】:

  • “我知道够危险” - 成就了我的一天
  • 请显示您的输入并指出导致问题的行。
  • $matches[0] will contain the text that matched the full pattern
  • . 匹配除换行符以外的所有字符。这包括选项卡。这可能是你的问题吗?

标签: php regex preg-match


【解决方案1】:

正则表达式引擎试图帮您一个忙并捕获最长的匹配。两个网址之间的\t 选项卡与.(点/任何字符)匹配。

演示:(Link)

$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 ---------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我建议的模式(如果您提供 smoe 示例字符串,我可能会改进模式)使用 (?:[^/\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

*note1:你可以使用\t,我使用\s,如果你想更字面化,我使用\s,因为有效的网址无论如何都不应该包含空格。您可以在项目中进行此调整而不会损失任何准确性。

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

【讨论】:

  • 如果我得到一行并将其放入变量或正则表达式测试器中,它就可以工作。只有当我在一个包含 5 mil 字符的同一个变量上循环运行它几次时,它才会中断。每行都是 id\ttitle\tdesc\tlink\timglink\t2ndimglink... 这是一个 Google 产品提要。我不明白为什么它会捕获 \t 因为它说要找到带有通配符的 http 部分并且必须以文件名结尾。为什么它在变量中是“imglink\t2ndimglink”时会返回“2ndimglink\timglink”?这怎么可能?
  • 我的“结晶”代码块是否不能很好地描述发生的情况? (我希望这听起来不会居高临下——这不是我的语气)
  • 我承认,由于格式的原因,我很难解读您的评论。您能否使用我提供的模式重新创建问题?我的模式也会失败吗?
  • 找到了真正的问题。我的搜索数据很糟糕。不知何故,我有一个次要图像而不是那个主要图像。我现在需要弄清楚。我在这件事上浪费了很多时间。在我投入的时间里,我本可以手动完成几次。
  • @DavidOgletree 没办法。如果你是一个学习者,你就不是失败者。尽管现在感觉很沮丧,但它会让你向前迈进。不管怎样,我希望你实现我的模式,因为它会比你原来的模式更有效率。 *我还应该说,如果您提供几行输入示例,我也许可以为您进一步完善我的模式。
猜你喜欢
  • 2014-04-24
  • 1970-01-01
  • 2017-03-10
  • 2011-08-18
  • 2016-07-22
  • 1970-01-01
  • 2014-09-04
  • 2015-10-05
  • 1970-01-01
相关资源
最近更新 更多