【问题标题】:Replace words in a string, but ignore HTML替换字符串中的单词,但忽略 HTML
【发布时间】:2011-12-14 10:42:32
【问题描述】:

我正在尝试编写一个高亮插件,并希望保留 HTML 格式。使用javascript进行替换时是否可以忽略字符串中之间的所有字符?

以以下为例:

var string = "Lorem ipsum dolor span sit amet, consectetuer <span class='dolor'>dolor</span> adipiscing elit.";

我希望能够实现以下目标(将 'dolor' 替换为 'FOO'):

var string = "Lorem ipsum FOO span sit amet, consectetuer <span class='dolor'>FOO</span> adipiscing elit.";

或者甚至是这个(将“span”替换为“BAR”):

var string = "Lorem ipsum dolor BAR sit amet, consectetuer <span class='dolor'>dolor</span> adipiscing elit.";

我非常接近在此处找到 tambler 给出的答案:Can you ignore HTML in a string while doing a Replace with jQuery?,但由于某种原因,我无法获得公认的答案。

我对正则表达式完全陌生,因此我们将不胜感激。

【问题讨论】:

  • Jon,试图用正则表达式解析 html 是出了名的困难。 stackoverflow.com/questions/1732348/…
  • 您应该解析 HTML,然后在每个文本节点上递归迭代。
  • @graphicdivine 他并没有试图解析它,他只是想改变一个单词而不修改元素内的任何内容
  • " 是否可以忽略字符串中 之间的所有字符" - 如果字符串包含类似“即使 4 5 Lorem ipsum dolor span 5 > 4."

标签: javascript regex


【解决方案1】:

使用浏览器的内置解析器通过innerHTML 解析HTML,然后遍历DOM 是明智的做法。这是一个基于this answer的松散答案:

现场演示:http://jsfiddle.net/FwGuq/1/

代码:

// Reusable generic function
function traverseElement(el, regex, textReplacerFunc) {
    // script and style elements are left alone
    if (!/^(script|style)$/.test(el.tagName)) {
        var child = el.lastChild;
        while (child) {
            if (child.nodeType == 1) {
                traverseElement(child, regex, textReplacerFunc);
            } else if (child.nodeType == 3) {
                textReplacerFunc(child, regex);
            }
            child = child.previousSibling;
        }
    }
}

// This function does the replacing for every matched piece of text
// and can be customized to do what you like
function textReplacerFunc(textNode, regex, text) {
    textNode.data = textNode.data.replace(regex, "FOO");
}

// The main function
function replaceWords(html, words) {
    var container = document.createElement("div");
    container.innerHTML = html;

    // Replace the words one at a time to ensure each one gets matched
    for (var i = 0, len = words.length; i < len; ++i) {
        traverseElement(container, new RegExp(words[i], "g"), textReplacerFunc);
    }
    return container.innerHTML;
}


var html = "Lorem ipsum dolor span sit amet, consectetuer <span class='dolor'>dolor</span> adipiscing elit.";
alert( replaceWords(html, ["dolor"]) );

【讨论】:

  • 感谢蒂姆这么好的回答。非常感谢!
  • 这是一个很好的解决方案,但是当您尝试在替换文本中包含 HTML 标记时,它们会被转义。例如,将搜索字符串加粗将导致 <string>
  • @Hawkee:是的。在搜索字符串中允许 HTML 完全改变了问题。
  • 抱歉,我上次的评论不正确,我的意思是用“string”替换“string”,结果是“<b>string</b>”尽管如此,我还是找到了一个效果很好的解决方案:stackoverflow.com/questions/11040770/…
  • 嘿,只是想知道是否有人可以帮助我如何插入 html 作为替换? textNode.data = textNode.data.replace(regex, "" + 'FOOO' + "");这实际上渲染出了带有内容的 span 标签,而不是将其视为 HTML Span 标签。非常感谢您提前提供的帮助!
【解决方案2】:

此解决方案适用于 perl,也应该适用于 Javascript,因为它与 ECMA 262 兼容:

s,\bdolor\b(?=[^"'][^&gt;]*&gt;),FOO,g

基本上,如果单词后面跟着不是引号的所有内容,然后是不是结束 &gt; 和结束 &gt; 本身的所有内容。

【讨论】:

  • 虽然我很遗憾无法让您的示例正常工作,但仍然感谢您的回答,fge。
  • 有人知道这个方法的正确 JS 语法吗?其他方法仅适用于每个单词,而不是采用由两个单词组成的字符串,其中一个单词可能被 HTML 标记包围。
猜你喜欢
  • 2020-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-26
  • 1970-01-01
  • 2014-08-16
  • 2015-07-03
相关资源
最近更新 更多