什么是最快的方法从特定标签中删除字符串

3

我有一个包含HTML的字符串。我想删除其中的<head>部分。我使用以下代码:

$html = preg_replace("/<head[^>]*?>.*?<\/head>/s", "", $html);

但是就性能而言,这可能会有些繁重。有更好的替代方案吗?

我知道可以使用 strip_tags() 函数,并在第二个参数中列出所有接受的标签,但要列出太多了。


你可以使用 strpos() 函数来确定开头和结尾的 <head> 标签的位置,然后获取子字符串,但我不确定这是否是更好的性能方式。 - Paul
6
你可以写出更好的正则表达式 :) 比如<head[^>]*?>[^<]*(?:<(?!\/head>)[^<]*)*<\/head>。与你的正则表达式进行比较。 - Wiktor Stribiżew
@WiktorStribiżew 就是这个!你能写出答案并解释一下它如何减少步骤等等吗?非常令人印象深刻。我可以在同一个正则表达式中添加更多的标签吗?比如 <head><header><nav>,这样我就可以一次性删除所有这些标签,而不是进行3次单独的reg_replace()运行。 - Gary Woods
3
也许你需要移除 <script><style> 标签内的所有内容。 - chris85
2
@ᴳᵁᴵᴰᴼ:很不幸,sax在PHP中非常慢,只能用于XML(与XMLReader相同,它是来自libxml的拉解析器,速度更快)。但由于似乎OP需要对其HTML源执行多个任务,因此使用DOMDocument并不是问题,树构建的成本将被摊销。 - Casimir et Hippolyte
显示剩余2条评论
1个回答

0

您当前的正则表达式在测试此 SO 页面的部分时需要 6720 步。

这个正则表达式 <head[^>]*?>(?:[^<]*<??)*</head> 仅需 376 步,且应返回相同结果。它应该比您的正则表达式快近20倍左右。

它通过贪婪匹配除了 < 之外的所有内容来工作:[^<]*

然后,由于 <?? 是懒惰模式,它将尝试立即匹配</head>。如果没有匹配,则会启动 <??


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接