【问题标题】:How to replace text not within a specific-Tag in JavaScript如何在 JavaScript 中替换不在特定标签内的文本
【发布时间】:2026-02-20 15:50:01
【问题描述】:

我有一个字符串(部分是 HTML),我想将字符串 :-) 替换为 bbcode :wink:。但是这种替换不应该发生在<pre> 内,而应该发生在任何其他标签中(甚至不在标签内)。

比如我要替换

:-)<pre>:-)</pre><blockquote>:-)</blockquote>

到:

:wink:<pre>:-)</pre><blockquote>:wink:</blockquote>

我已经用下面的 RegEx 尝试过了,但它不起作用(没有被替换):

var s = ':-)<pre>:-)</pre><blockquote>:-)</blockquote>';
var regex = /:\-\)(?!(^<pre>).*<\/pre>)/g;
var r = s.replace(regex, ':wink:');

有人可以帮帮我吗? :-)

【问题讨论】:

  • 不要尝试用正则表达式解析 HTML 节点; HTML 不是常规的。使用适当的 HTML 解析器来生成 DOM - 对于 JavaScript,jQuery 是一个理想的选择。

标签: javascript regex html-parsing


【解决方案1】:

应该这样做:-

var src = ":-)<pre>:-)</pre><blockquote>:-)</blockquote>"

var result = src.replace(/(<pre>(?:[^<](?!\/pre))*<\/pre>)|(\:\-\))/gi, fnCallback)

function fnCallback(s)
{
    if (s == ":-)") return ":wink:"
    return s;
}

alert(result);

之所以有效,是因为任何pre 元素都将被正则表达式中的第一个选项拾取,并且一旦使用意味着任何包含的:-) 都无法匹配,因为处理器将超出它。

【讨论】:

  • 谢谢!这行得通,唯一的小错误是函数定义必须在函数调用之前 - 但这很容易解决;-)
  • 很高兴它解决了你的问题,但我很好奇你为什么觉得函数定义需要在调用之前?它在我的测试工具中运行良好。 Javascript 在执行块之前在执行块中创建所有函数定义。你在考虑函数表达式吗?
  • @Gutzofter:它是一个超级强大的超级测试工具:-
  • 函数 writeLn(s) { WScript.Echo(s); }\n alert = writeLn\n \\你的代码在这里。 ;)
  • @Anthony:我将您的解决方案复制/粘贴到 Firebug 控制台中进行测试,只要函数定义在函数调用之前,它就无法工作。我不得不承认我没有在真正的代码中测试它(只是在之后实现了它)。
【解决方案2】:

如果你使用合适的库,比如 jQuery,你可以完全避免地狱般的正则表达式,例如:

var excludeThese = ['pre'];

// loop over all elements on page, replacing :-) with :wink: for anything
// that is *not* a tag name in the excludeThese array

$('* not:(' + excludeThese.join(',') + ')').each(function() {
    $(this).html($(this).html().replace(/:\-\)/,':wink:'));
});

【讨论】:

  • .html() 返回一个字符串。因此 .replace 是一个正则表达式替换。
  • 我总是犯这个错误,感谢指出,已修复。这真的值得否决吗?
  • 谢谢,我已经用原型了,你知道那里是怎么做的吗?
  • 可能不是它自己的,已删除反对票。然而,当一个问题是关于 javascript 并且没有指定 JQuery 时,我确实找到了引入 JQuery 的答案,这会不必要地令人恼火。我几乎不会说您的 JQuery 代码比针对所提出问题的纯正则表达式/Javascript 解决方案要少得多“地狱”。因此,再加上仍然需要正则表达式并且您的答案实际上并没有奏效,这足以让您投反对票。
【解决方案3】:

只是觉得值得提供一个 DOM 解决方案:

例如

var div = document.createElement('div');
div.innerHTML = ":-)<pre>:-)</pre><blockquote>:-)</blockquote>";

replace(div, /:-\)/g, ":wink:", function(){

    // Custom filter function.
    // Returns false for <pre> elements.

    return this.nodeName.toLowerCase() !== 'pre';

});

div.innerHTML; // <== here's your new string!

这是replace 函数:

function replace(element, regex, replacement, filter) {

    var cur = element.firstChild;

    if (cur) do {

        if ( !filter || filter.call(cur) ) {

            if ( cur.nodeType == 1 ) {
                replace( cur, regex, replacement );
            } else {
                cur.data = cur.data.replace( regex, replacement );
            }

        }

    } while ( cur = cur.nextSibling );

}

【讨论】:

    【解决方案4】:

    试试 var 正则表达式 = /:-)(?!(^)*)/g;

    【讨论】:

    • 遗憾的是,这仅适用于除了“:-)”之外没有其他标志的情况。例如,使用 ":-)
       :-) 
      :-)
      " 会失败。