preg_match_all突然停止在文本中查找事件

时间:2013-06-12 18:41:55

标签: php fedora preg-match-all pcre

我有使用preg_match_all在电子邮件正文中查找出现的代码。像这样:

$sHrefPattern = "<(a|area)\s*.*(unsubscribe_url\s*=\s*?)([\"\']??)([^\" >]*?)";
if (preg_match_all("/$sHrefPattern/siU", $sHtmlBody, $aMatches, PREG_SET_ORDER)) {
    // do smth ...
}

和这样的内容(可以包含俄语文本出现):

... <td align="left" colspan="3" height="22" valign="center">
    <a style="font-size: 8pt; color: #666; padding-left: 13px; font-family: arial;" unsubscribe_url="http://ourcliensite.org/unsubscribe.html">
        Unsubscribe
    </a> |
    <a href="http://ourservice.com/linkswrap?did=819&sid=1&link=http%3A%2F%2Fwww.ourclinetsite.org&dig=7bef6d9ed912392a689bdb9bb6cc581d" style="font-size: 8pt; color: #666; padding-left: 13px; font-family: arial;">
        Advertisement in emails
    </a>
</td> ...

很长一段时间,这段代码运行良好。但有一天,这段代码停止正常工作。我认为它与某些软件包安装有关,但我不知道安装了哪个软件包。此代码正在运行的服务器已在我们的团队中进行共享访问。有什么想法吗?

uname -a
Linux ourhost 2.6.32-042stab076.8 #1 SMP Tue May 14 20:38:14 MSK 2013 i686 i686 i386    GNU/Linux

2 个答案:

答案 0 :(得分:1)

检查所涉及的字符集。我不知道任何关于php在这方面的最新变化,但你的正则表达式也包含俄语吗?您使用的是8位西里尔字符集还是UTF-8?是由PHP明确设置还是检测?也许你的代码只是忽略了编码问题,而某些默认值在某处发生了变化。我建议调试它,好像它是新代码。找到失败的正则表达式,找到失败的小输入,并尝试确定其编码。

正则表达式可以使用u修饰符智能地处理unicode,所以我先尝试一下,以防它自动修复所有内容。

答案 1 :(得分:1)

我认为邪恶的人在你睡着时编辑了你的模式,幸运的是,我建议你测试这种模式来取代旧模式:

$sHrefPattern = "<a(?>rea)?\b(?>[^u]++|u++(?!nsubscribe_url\b))+"
               ."unsubscribe_url\s*+=\s*+[\"']?+\K[^\"'\s]++";
preg_match_all("/$sHrefPattern/iu", $sHtmlBody, $aMatches, PREG_SET_ORDER);
print_r($aMatches);

它针对快速失败进行了优化,同时注意新标志,现在结果是整个模式(不需要捕获组),(即组0)。