我有一个充满了我需要匹配的模式的数组。除了 for() 循环之外,还有什么方法可以做到这一点?我试图以 CPU 密集度最低的方式来做这件事,因为我每分钟都会做几十个这样的事情。
现实世界的例子是,我正在构建一个链接状态检查器,它将检查各种在线视频网站的链接,以确保视频仍然是实时的。每个域都有几个“死关键词”,如果在页面的 html 中找到这些,则意味着该文件已被删除。这些存储在数组中。我需要将数组的内容与页面的 html 输出相匹配。
我有一个充满了我需要匹配的模式的数组。除了 for() 循环之外,还有什么方法可以做到这一点?我试图以 CPU 密集度最低的方式来做这件事,因为我每分钟都会做几十个这样的事情。
现实世界的例子是,我正在构建一个链接状态检查器,它将检查各种在线视频网站的链接,以确保视频仍然是实时的。每个域都有几个“死关键词”,如果在页面的 html 中找到这些,则意味着该文件已被删除。这些存储在数组中。我需要将数组的内容与页面的 html 输出相匹配。
首先,如果您实际上每分钟只做几十次,那么我不会非常担心这种情况下的性能。这些匹配非常快,我认为通过遍历您的模式数组并像这样单独调用 preg_match 不会出现性能问题:
$matches = false;
foreach ($pattern_array as $pattern)
{
if (preg_match($pattern, $page))
{
$matches = true;
}
}
您确实可以or
像某些人建议的那样使用运算符将所有模式组合成一个,但不要只是将它们与|
. 如果您的任何模式包含or 运算符,这将严重破坏。
我建议至少使用括号对您的模式进行分组,例如:
foreach ($patterns as $pattern)
{
$grouped_patterns[] = "(" . $pattern . ")";
}
$master_pattern = implode($grouped_patterns, "|");
但是......我不确定这是否会更快。 有些东西必须循环通过它们,无论是 preg_match 还是 PHP。如果我不得不猜测,我会猜测单个匹配会接近相同的速度,并且更容易阅读和维护。
最后,如果性能是您在这里寻找的,我认为最重要的事情是将非正则表达式匹配提取到一个简单的“字符串包含”检查中。我想您的某些检查必须是简单的字符串检查,例如查看“此站点已关闭”是否在页面上。
所以这样做:
foreach ($strings_to_match as $string_to_match)
{
if (strpos($page, $string_to_match) !== false))
{
// etc.
break;
}
}
foreach ($pattern_array as $pattern)
{
if (preg_match($pattern, $page))
{
// etc.
break;
}
}
尽可能多地避免preg_match()
可能是你最大的收获。 strpos()
比快很多preg_match()
。
// assuming you have something like this
$patterns = array('a','b','\w');
// converts the array into a regex friendly or list
$patterns_flattened = implode('|', $patterns);
if ( preg_match('/'. $patterns_flattened .'/', $string, $matches) )
{
}
// PS: that's off the top of my head, I didn't check it in a code editor
如果您的模式不包含很多空格,另一种选择是避开数组并使用/x
修饰符。现在您的正则表达式列表将如下所示:
$regex = "/
pattern1| # search for occurences of 'pattern1'
pa..ern2| # wildcard search for occurences of 'pa..ern2'
pat[ ]tern| # search for 'pat tern', whitespace is escaped
mypat # Note that the last pattern does NOT have a pipe char
/x";
使用/x
修饰符时,空格将被完全忽略,除非在字符类中或前面有反斜杠。像上面这样的评论也是允许的。
这将避免遍历数组。
如果您只是在另一个字符串中搜索字符串的存在,请使用 strpos,因为它更快。
否则,您可以迭代模式数组,每次调用 preg_match 。
如果你有一堆模式,你可以做的就是将它们连接到一个正则表达式中并匹配它。不需要循环。
对使用数组得到的 HTML进行 astr_replace()
处理然后检查原始 HTML 是否等于原始 HTML 怎么样?这将非常快:
$sites = array(
'you_tube' => array('dead', 'moved'),
...
);
foreach ($sites as $site => $deadArray) {
// get $html
if ($html == str_replace($deadArray, '', $html)) {
// video is live
}
}
您可以使用implode() php 函数将列表中的所有模式组合成单个正则表达式。然后使用preg_match() php 函数一次测试你的字符串。
$patterns = array(
'abc',
'\d+h',
'[abc]{6,8}\-\s*[xyz]{6,8}',
);
$master_pattern = '/(' . implode($patterns, ')|(') . ')/'
if(preg_match($master_pattern, $string_to_check))
{
//do something
}
当然,在“if()”条件而不是$master_pattern
变量中使用 implode() 内联代码可能会更少。