【问题标题】:JavaScript RegExp match text ignoring HTMLJavaScript RegExp 匹配文本忽略 HTML
【发布时间】:2011-09-07 19:02:39
【问题描述】:

是否可以在“The <strong>dog</strong> is really <em>really</em> fat!”中匹配“这只狗真的很胖”,并在其周围加上“<span class="highlight">WHAT WAS MATCHED</span>”?

我不是这个意思,但通常能够搜索文本忽略 HTML,将其保留在最终结果中,然后只需在上面添加跨度?

编辑:
考虑到 HTML 标签重叠问题,是否可以匹配一个短语并在每个匹配的单词周围添加跨度?这里的问题是我不希望“狗”这个词不在搜索的上下文中时匹配,在这种情况下,“狗真的很胖。”

【问题讨论】:

  • 一般情况下不会。不要对 HTML 使用 RegEx。使用 HTML 解析器。另外,请使用 StackOverflow 中的代码高亮功能。
  • 他不是,他只是想匹配特定的文本。
  • 除了 JavaScript 之外,我没有其他可以接触的东西。我以为我使用了反引号而不是引号。
  • 情况比这更糟。 <strong>I say the</strong> dog is <em>really really fat! What do</em> you say? 怎么样?你打算让这个看起来像:<strong>I say <span class="highlight">the</strong> dog is <em>really really fat!</span> What do</em> you say?
  • 好问题,这很糟糕......

标签: javascript regex


【解决方案1】:

更新:

这是一个可以做你想做的工作的小提琴。但是,您将需要更新 htmlTagRegEx 以处理任何 HTML 标记的匹配,因为这只是执行简单的匹配并且不会处理所有情况。

http://jsfiddle.net/briguy37/JyL4J/

另外,下面是代码。基本上,它一个一个地取出 html 元素,然后在文本中进行替换以在匹配的选择周围添加突出显示范围,然后一个一个地推回 html 元素。这很难看,但这是我能想到的最简单的让它工作的方法......

function highlightInElement(elementId, text){
    var elementHtml = document.getElementById(elementId).innerHTML;
    var tags = [];
    var tagLocations= [];
    var htmlTagRegEx = /<{1}\/{0,1}\w+>{1}/;

    //Strip the tags from the elementHtml and keep track of them
    var htmlTag;
    while(htmlTag = elementHtml.match(htmlTagRegEx)){
        tagLocations[tagLocations.length] = elementHtml.search(htmlTagRegEx);
        tags[tags.length] = htmlTag;
        elementHtml = elementHtml.replace(htmlTag, '');
    }

    //Search for the text in the stripped html
    var textLocation = elementHtml.search(text);
    if(textLocation){
        //Add the highlight
        var highlightHTMLStart = '<span class="highlight">';
        var highlightHTMLEnd = '</span>';
        elementHtml = elementHtml.replace(text, highlightHTMLStart + text + highlightHTMLEnd);

        //plug back in the HTML tags
        var textEndLocation = textLocation + text.length;
        for(i=tagLocations.length-1; i>=0; i--){
            var location = tagLocations[i];
            if(location > textEndLocation){
                location += highlightHTMLStart.length + highlightHTMLEnd.length;
            } else if(location > textLocation){
                location += highlightHTMLStart.length;
            }
            elementHtml = elementHtml.substring(0,location) + tags[i] + elementHtml.substring(location);
        }
    }

    //Update the innerHTML of the element
    document.getElementById(elementId).innerHTML = elementHtml;
}

【讨论】:

  • 谢谢,但我需要匹配文本并仍然保留标签。
  • @Francisc:对文本进行文本匹配。如果匹配,则使用 innerHTML 获取 html。
  • 是的,但是 innerHTML 是什么?文本可以是:&lt;p&gt;The dog is &lt;i&gt;really really&lt;/i&gt; fat.&lt;/p&gt;,我想找到dog is really 并在其周围添加&lt;span&gt;,但这会与&lt;i&gt; 元素重叠。
  • @Francisc:抱歉之前的误会。请检查我更新的解决方案,因为我认为它现在可以解决您需要做的事情。如果您使用它,我绝对建议您研究更彻底的正则表达式。
  • 哇,写这肯定花了一些时间。非常感谢。
【解决方案2】:

不...只需使用旧的正则表达式;)

var htmlString = "The <strong>dog</strong> is really <em>really</em> fat!";
var regexp = /<\/?\w+((\s+\w+(\s*=\s*(?:\".*?"|'.*?'|[^'\">\s]+))?)+\s*|\s*)\/?>/gi;
var result = '<span class="highlight">' + htmlString.replace(regexp, '') + '</span>';

【讨论】:

  • 这看起来很可爱...是圣诞节了吗?无论如何,我认为这不会解决重叠 HTML 标签的问题,对吗?
  • 你在哪里输入搜索词? :)
  • 对不起,我错过了最后一个.. regexp 将匹配每个 html 标签
  • 哦,我想我明白了,它会去掉所有的 HTML 标签,对吧?
  • 啊,是的,我需要的是让它在人类阅读时匹配一些文本并添加 hightlight 类。 :)
【解决方案3】:

使用 JQuery 的更简单的方法是。

originalHtml = $("#div").html();

    newHtml = originalHtml.replace(new RegExp(keyword + "(?![^<>]*>)", "g"), function(e){
                      return "<span class='highlight'>" + e + "</span>";
                   });

$("#div").html(newHtml);

这对我来说很好用。

【讨论】:

    【解决方案4】:

    这是一个有效的正则表达式示例,用于排除 html 标记和 javascripts 中的匹配项:

    http://refiddle.com/lwy6

    在 replace() 脚本中使用此正则表达式。

        /(a)(?!([^<])*?>)(?!<script[^>]*?>)(?![^<]*?<\/script>|$)/gi
    

    【讨论】:

      【解决方案5】:

      你可以用这个表达式&lt;/?\w*&gt; 使用字符串替换,你会得到你的字符串

      【讨论】:

        【解决方案6】:
        this.keywords.forEach(keyword => {
          el.innerHTML = el.innerHTML.replace(
            RegExp(keyword + '(?![^<>]*>)', 'ig'),
            matched => `<span class=highlight>${matched}</span>`
          )
        })
        

        【讨论】:

          【解决方案7】:

          如果您使用 jQuery,您可以在包含您要搜索的文本的元素上使用 text 属性。鉴于此标记:

          <p id="the-text">
            The <strong>dog</strong> is really <em>really</em> fat!
          </p>
          

          这会产生“这只狗真的很胖!”:

          $('#the-text').text();
          

          您可以对该文本进行正则表达式搜索,而不是尝试在标记中这样做。

          如果没有 jQuery,我不确定从所有子元素中提取和连接文本节点的简单方法。

          【讨论】:

          • 我不认为我可以使用 jQuery。
          • 哦,是的,我忘记了 jQuery 文本。为什么不能使用 jQuery?
          猜你喜欢
          • 1970-01-01
          • 2019-07-29
          • 1970-01-01
          • 1970-01-01
          • 2011-12-13
          • 2011-08-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多