【问题标题】:highlight words in html using regex & javascript - almost there使用正则表达式和 javascript 突出显示 html 中的单词 - 几乎就在那里
【发布时间】:2012-05-02 15:16:51
【问题描述】:

我正在编写一个 jquery 插件,它将执行浏览器样式的页面查找搜索。我需要改进搜索,但还不想完全解析 html。

目前我的方法是获取整个 DOM 元素和所有嵌套元素,然后简单地为给定术语运行正则表达式查找/替换。在替换中,我将简单地在匹配的术语周围包裹一个跨度,并将该跨度用作我的锚点来进行突出显示、滚动等。任何 html 标记中的字符都不能匹配,这一点至关重要。 p>

这是我得到的最接近的:

(?<=^|>)([^><].*?)(?=<|$)

它很好地捕获了 html 标记中 的所有字符,但我无法弄清楚如何插入我的搜索词。

Input: Any html element (this could be quite large, eg <body>)    
Search Term: 1 or more characters    
Replace Txt: <span class='highlight'>$1</span>

更新

当我使用http://gskinner.com/RegExr/ 进行测试时,以下正则表达式可以满足我的需求...

Regex: (?<=^|>)(.*?)(SEARCH_STRING)(?=.*?<|$)
Replacement: $1<span class='highlight'>$2</span>

但是我在我的 javascript 中使用它时遇到了一些问题。使用以下代码,chrome 给我错误“无效的正则表达式:/(?)(.?)(Mary)(?=.?

var origText = $('#'+opt.targetElements).data('origText');
var regx = new RegExp("(?<=^|>)(.*?)(" + $this.val() + ")(?=.*?<|$)", 'gi');
$('#'+opt.targetElements).each(function() {
   var text = origText.replace(regx, '$1<span class="' + opt.resultClass + '">$2</span>');
   $(this).html(text);
});

它在组中中断 (?) - 这是笨拙的东西还是正则表达式引擎的差异?

更新

这个正则表达式在该组中中断的原因是因为 Javascript 不支持正则表达式后视。供参考和可能的解决方案:http://blog.stevenlevithan.com/archives/mimic-lookbehind-javascript

【问题讨论】:

  • sigh 请不要使用 RegEx 解析 HTML,因为它会 drive you insane。请改用HTML parser
  • 我有一个转向 html 解析的计划,但我需要一个快速的概念验证才能获得批准。
  • 你应该把它作为你的概念证明,而不是 RegExp。这是一个已解决的问题,请不要过度使用 RegExp。
  • @Truth:感谢您的关注。请停止。我同意你的说法并接受你明显的议程。我的问题是,如何在这个正则表达式字符串中插入搜索词?
  • 看看mark.js,因为它可能是您正在寻找的东西。

标签: html regex replace


【解决方案1】:

只需使用 jQuerys 内置的text() method。它将返回选定 DOM 元素中的所有字符。

对于 DOM 方法 (docs for the Node interface):遍历元素的所有子节点。如果子节点是元素节点,则递归运行。如果是文本节点,请在文本中搜索 (node.data),如果要突出显示/更改某些内容,请缩短节点的文本直到找到的位置,然后插入匹配文本和另一个文本节点的 highligth-span其余的文本。

示例代码(调整后,原点为here):

(function iterate_node(node) {
    if (node.nodeType === 3) { // Node.TEXT_NODE
        var text = node.data,
            pos = text.search(/any regular expression/g), //indexOf also applicable
            length = 5; // or whatever you found
        if (pos > -1) {
            node.data = text.substr(0, pos); // split into a part before...
            var rest = document.createTextNode(text.substr(pos+length)); // a part after
            var highlight = document.createElement("span"); // and a part between
            highlight.className = "highlight";
            highlight.appendChild(document.createTextNode(text.substr(pos, length)));
            node.parentNode.insertBefore(rest, node.nextSibling); // insert after
            node.parentNode.insertBefore(highlight, node.nextSibling);
            iterate_node(rest); // maybe there are more matches
        }
    } else if (node.nodeType === 1) { // Node.ELEMENT_NODE
        for (var i = 0; i < node.childNodes.length; i++) {
            iterate_node(node.childNodes[i]); // run recursive on DOM
        }
    }
})(content); // any dom node

还有highlight.js,这可能正是你想要的。

【讨论】:

  • 我知道如何使用 .text() 来获取和替换元素的文本,但我看不出如何使用它来搜索/替换该元素文本的子集。示例:我只想在长

    元素中突出显示单词“and”。想法?

  • 那么您可能需要使用native DOM 方法并更改文本节点。
  • 酷。我现在很好,但是当我在这个项目上获得成功时,我想我会先尝试这种方法。使用 jquery :contains 方法 (api.jquery.com/contains-selector/) 我应该能够在 DOM 中找到我的搜索词。一旦我有了这些元素,根据需要操作 .text() 应该是相当简单的。谢谢伯吉。
  • 哎呀——说得太早了。 $(#target *:contains('text')) 在查找元素方面做得很好,但它会返回包含元素。该元素包含内容、我的搜索词和其他 html 的混合。使用 .text() 会去除标签(不可接受),而 .html() 则让我遇到了为搜索词搜索混合内容和标记的原始问题。 :contains() 缩小了竞争范围,但搜索/替换问题仍然存在。 @Bergi,你有没有想过一种特定的原生 DOM 方法?
  • 是的,我已经编写了各种文本节点迭代器 :) 评论太长了,请扩展我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-16
  • 1970-01-01
  • 2012-02-17
  • 2011-08-20
相关资源
最近更新 更多