【问题标题】:JavaScript Global Regex is not GlobalJavaScript 全局正则表达式不是全局的
【发布时间】:2014-10-26 07:33:56
【问题描述】:

我正在尝试创建一个简单的扩展,将某些单词替换为其他单词。我正在使用正则表达式来查找全局匹配,然后使用条件来替换单词。但是,尽管我指定了“gi”,但它只替换了每个单词的第一次出现。谁能解释它为什么表现出这种行为?

我从这里得到了一些代码:Javascript Regex to replace text NOT in html attributes

代码如下:

Fiddle

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

// Reusable generic function
function surroundMatchingText(textNode, regex, surrounderCreateFunc) {
    var parent = textNode.parentNode;
    var result, surroundingNode, matchedTextNode, matchLength, matchedText;
    while ( textNode && (result = regex.exec(textNode.data)) ) {
        matchedTextNode = textNode.splitText(result.index);
        matchedText = result[0];
        matchLength = matchedText.length;
        textNode = (matchedTextNode.length > matchLength) ?
            matchedTextNode.splitText(matchLength) : null;
        surroundingNode = surrounderCreateFunc(matchedTextNode.cloneNode(true));
        parent.insertBefore(surroundingNode, matchedTextNode);
        parent.removeChild(matchedTextNode);
    }
}

// This function does the surrounding for every matched piece of text
// and can be customized  to do what you like
function createSpan(matchedTextNode) {
    var val = matchedTextNode.nodeValue;
    var valuelower = val.toLowerCase();
    if(valuelower === "nice" || valuelower === "good" || valuelower === "great" || valuelower === "awesome" || valuelower === "amazing"){
        var t = document.createTextNode("gj");
        var el = document.createElement("span");
        el.style.color = "red";
        el.appendChild(t);
        return el;
    }

    if(valuelower === "bad" || valuelower === "terrible" || valuelower === "horrendous" || valuelower === "awful" || valuelower === "abominable"){
        var t = document.createTextNode("bj");
        var el = document.createElement("span");
        el.style.color = "red";
        el.appendChild(t);
        return el;
    }

    if(valuelower === "does"){
        var t = document.createTextNode("dose");
        var el = document.createElement("span");
        el.style.color = "red";
        el.appendChild(t);
        return el;
    }
}

// The main function
function wrapWords(container, words) {
    // Replace the words one at a time.
    for (var i = 0, len = words.length; i < len; ++i) {
        surroundInElement(container, new RegExp(words[i], "gi"), createSpan);
    }
}

wrapWords(document.body, ["nice", "good", "great", "awesome", "amazing", "bad", "terrible", "horrendous", "awful", "abominable", "does"]);

【问题讨论】:

  • 忽略详细问题。你能解释一下代码背后的整体想法吗?我了解您想替换页面上的单词。但您是指在特定元素、整个页面等中吗?
  • 删除“g”它将解决您的问题。正则表达式有点损坏(行为怪异) - 正则表达式也不会被重置 - 所以在每次连续执行时,它都会从最后一个匹配索引继续 - 尝试 xregexp.com 代替
  • @SReject,代码的目的是解析 DOM 树,只更改可见的单词,而不是隐藏 HTML div 等中的单词。 Dinesh,效果很好。谢谢!

标签: javascript regex dom


【解决方案1】:

这是因为 regex.exec 方法返回“下一个”匹配,从最后一个匹配的结尾开始。您正在做的是为您创建的每个 RegExp 对象获取第一个匹配项,进行替换,然后转到下一个 RegExp 对象。

您需要再次运行正则表达式,但在匹配每个正则表达式对象的最后一个节点结束的位置启动它。使用您当前的代码很简单,只需移除“g”开关即可。

【讨论】:

    猜你喜欢
    • 2013-11-23
    • 1970-01-01
    • 2011-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多