php正则表达式匹配html标签之外

Posted

技术标签:

【中文标题】php正则表达式匹配html标签之外【英文标题】:php regex to match outside of html tags 【发布时间】:2011-12-15 01:27:20 【问题描述】:

我正在 html 页面上进行 preg_replace。我的模式旨在为 html 中的某些单词添加环绕标记。但是,有时我的正则表达式会修改 html 标签。例如,当我尝试替换此文本时:

<a href="example.com" >yasar</a>

所以 yasar 读取 &lt;span class="selected-word"&gt;yasar&lt;/span&gt; ,我的正则表达式也替换了锚标记的 alt 属性中的 yasar。我正在使用的当前preg_replace() 看起来像这样:

preg_replace("/(asf|gfd|oyws)/", '<span class=something>$1</span>',$target);

如何制作正则表达式,使其不匹配 html 标签内的任何内容?

【问题讨论】:

@MarcB 一次,我认为这是一个有效的正则表达式问题。使用 DOM 解析器很难轻松地完成 OP 想要的操作。他只需要知道如何不匹配引号内的单词。 @Xeon:还是个坏主意。使用 dom/xpath 获取文本节点,然后单独操作它们。这是唯一 100% 可靠的方法,可以确保您只处理“相关”文本,而不是匹配的格式错误的标签的一些不可靠的子块。 【参考方案1】:

您可以为此使用断言,因为您只需要确保搜索的单词出现在 &gt; 之后或任何 &lt; 之前的某个时间。后一种测试更容易完成,因为前瞻断言可以是可变长度的:

/(asf|foo|barr)(?=[^>]*(<|$))/

另请参阅http://www.regular-expressions.info/lookaround.html 以获得对该断言语法的很好解释。

【讨论】:

Yada yada,愚蠢的 bobince 回答... -- 是的,这不太正确。此正则表达式仅适用于 XML/XHTML,并且仅适用于没有 CDATA 边缘情况等。但即使在现实世界的 HTML 中,您也不会在属性中看到尖括号。因此,可以作为基本解决方案。 我在尝试运行您的正则表达式时收到Compilation failed: lookbehind assertion is not fixed length at offset 27。也许你错过了什么? 再试一次。自此编辑代码。 (有一个?&lt;= 应该是?=。) 我不知道这是如何工作的,因为我对前瞻概念不熟悉,但它确实有效。谢谢:) @likeforex.com:我们这里不做个人支持,SO 也不是论坛;没有规定在两者之间讨论不同的话题。特别是如果查询是那么模糊。 (“你试过什么?”)。我不知道你想要什么。 -- 如需帮助,请参阅 Open source RegexBuddy alternatives 和 Online regex testing 以获得一些有用的工具,或 RegExp.info 以获得更好的教程。【参考方案2】:

Yasar,重新提出这个问题,因为它有另一个未提及的解决方案。

此解决方案不只是检查下一个标记字符是否为开始标记,而是跳过所有&lt;full tags&gt;

关于使用正则表达式解析 html 的所有免责声明,这里是正则表达式:

<[^>]*>(*SKIP)(*F)|word1|word2|word3

这是demo。在代码中,它看起来像这样:

$target = "word1 <a skip this word2 >word2 again</a> word3";
$regex = "~<[^>]*>(*SKIP)(*F)|word1|word2|word3~";
$repl= '<span class="">\0</span>';
$new=preg_replace($regex,$repl,$target);
echo htmlentities($new);

这是此代码的online demo。

参考

    How to match pattern except in situations s1, s2, s3 How to match a pattern unless...

【讨论】:

【参考方案3】:

这可能是你所追求的:http://snipplr.com/view/3618/ 一般来说,我建议不要这样做。更好的选择是去掉所有的 HTML 标签,转而依赖 BBcode,例如:

[b]bold text[b] [i]italic text[i]

但我很感激这可能不适用于您正在尝试做的事情。

另一个选项可能是 HTML Purifier,请参阅:http://htmlpurifier.org/

【讨论】:

【参考方案4】:

在我看来,这应该可行:

echo preg_replace("/<(.*)>(.*)<\/(.*)>/i","<$1><span class=\"some-class\">$2</span></$3>",$target);

但是,我不知道这有多安全。我只是提出一种可能性:)

【讨论】:

以上是关于php正则表达式匹配html标签之外的主要内容,如果未能解决你的问题,请参考以下文章

高级正则技巧PHP正则表达式过滤html标签属性(DEMO)

如何与正则表达式匹配PHP中除“-”之外的所有特殊字符?

PHP正则表达式函数

正则表达式:匹配除特定模式之外的所有内容

正则匹配连续多个P标签

正则表达式 - 如何匹配除特定模式之外的所有内容