【问题标题】:Remove empty tags using RegEx使用 RegEx 删除空标签
【发布时间】:2021-05-03 01:46:52
【问题描述】:

我想删除空标签,例如<label></label><font> </font>,这样:

<label></label><form></form>
<p>This is <span style="color: red;">red</span> 
<i>italic</i>
</p>

将被清理为:

<p>This is <span style="color: red;">red</span> 
<i>italic</i>
</p>

我在 javascript 中有这个 RegEx,但它删除了空标签,但它也删除了这个:"&lt;i&gt;italic&lt;/i&gt;&lt;/p&gt;"

str=str.replace(/<[\S]+><\/[\S]+>/gim, "");

我错过了什么?

【问题讨论】:

  • 我认为堆栈溢出的标记可能会惹恼你。在我们看来,您的清理例行程序之前和之后的结果是一样的。
  • 这两行看起来一样。您可以使用代码块使文本不被格式化吗?
  • 修复了标记,bods,希望这更有意义。
  • 这个论坛这么快?我不敢相信你们这么快!!

标签: javascript regex


【解决方案1】:

您有“非空格”作为您的字符类,这意味着“&lt;i&gt;italic&lt;/i&gt;&lt;/p&gt;”将匹配。正则表达式的前半部分将匹配“&lt;(i&gt;italic&lt;/i)&gt;”和后半部分“&lt;/(p)&gt;”。 (我使用方括号来显示每个 [\S]+ 匹配的内容。)

改变这个:

/<[\S]+><\/[\S]+>/

到这里:

/<[^/>][^>]*><\/[^>]+>/

总的来说,您确实应该使用适当的 HTML 处理器,但如果您正在使用 HTML 汤,这应该就足够了 :)

【讨论】:

  • 这是最接近的表达式。其他的不工作。但是这个也删除了。我正在玩代码。谢谢
  • @AndreasJohansson:除非您解析一些 非常 混乱的 HTML,否则它不会真正产生影响。
  • 如果出现类似“
    instagram.com/"></blockquote>",这些都会失败。所以我更喜欢这个正则表达式:]+|[^ \/>]*["\'][^"\'>]*["\'][^\/>]+)>\s*]+>
【解决方案2】:

正则表达式不适用于 HTML。如果你仍然使用 JavaScript,我会被鼓励使用 jQuery DOM 处理。

类似:

$('*:empty').remove();

或者:

$("*").filter(function() 
{ 
     return $.trim($(this).html()).length > 0; 
}).remove();

【讨论】:

  • 我在同一个函数中有其他正则表达式清理。不幸的是,我更喜欢这种方式。内容位于用户从 word doc 粘贴的 IFrame 中。我正在清理所有 MSFT 垃圾
  • 我会研究 JQuery 选项。
  • 我同意正则表达式 似乎 更容易,但如果你已经在使用 javascript,那么 jQuery 就容易多了,而且扩展功能也变得容易多了(如果有需求呢?要求您开始删除嵌套的

    标记,或嵌套深度超过 3 层的标记?)

  • 我正在使用 jquery。在使用 jquery 之前,我还没有进行过这种类型的清理。任何简单的例子都会有所帮助.. 谢谢
  • 我知道格式无法在评论中解决,但复制并粘贴到您文档的开头:&lt;script type="text/javascript"&gt; $(document).ready(function() { $('*:empty').remove(); }); &lt;/script&gt; 等待文档准备好它的作用然后它会删除空标签(根据 Graphain 的示例)。确保首先加载 jQuery 库,例如&lt;script type="text/javascript" src="jquery.min.js"&gt;&lt;/script&gt;
【解决方案3】:

所有正则表达式的答案都只是验证

<label></label>

但是在

的情况下
<label> </label>
<label>    </label>
<label>
</label> 

试试这个模式以获得以上所有内容

<[^/>]+>[ \n\r\t]*</[^>]+>

【讨论】:

  • 如果我有'ul'后跟'li',它也会考虑在内。我怎么会跳过呢?
  • 我建议用[\s]* 替换[\n\r\t]*,这意味着同样的事情加上更多的(\f 和\v)和空间......
【解决方案4】:

您需要/&lt;[\S]+?&gt;&lt;\/[\S]+?&gt;/ - 区别在于+s 之后的?s,以匹配“尽可能少”(也称为“非贪婪匹配”)非空格字符(尽管 1 个或更多) ,而不是匹配“尽可能多”(又名“贪婪匹配”)的裸 +s。

正如另一个答案所建议的那样,完全避免正则表达式也是一个好主意,但我想指出重要的贪婪与非贪婪区别,这将在正则表达式 保证的。

【讨论】:

    【解决方案5】:

    我喜欢 MattMitchell 的 jQuery 解决方案,但这里有另一个使用原生 JavaScript 的选项。

    function CleanChildren(elem)
    {
        var children = elem.childNodes;
        var len = elem.childNodes.length;
    
        for (var i = 0; i < len; i++)
        {
            var child = children[i];
    
            if(child.hasChildNodes())
                CleanChildren(child);
            else
                elem.removeChildNode(child);
    
        }
    }
    

    【讨论】:

      【解决方案6】:

      这是一个现代原生 JavaScript 解决方案;这实际上与 2010 年的 jQuery 非常相似。我根据我正在从事的项目的答案改编它,并认为我会在这里分享它。

      document.querySelectorAll("*:empty").forEach((x)=>{x.remove()});
      
      • document.querySelectorAll 返回一个NodeList;它本质上是一个所有 DOM 节点的数组,这些节点与作为参数提供给它的 CSS 选择器匹配。

        • *:empty 是一个选择器,它选择所有为空的元素(* 表示“任何元素”)(这是 :empty 的意思)。

          这将选择整个文档中的任何空元素,如果您只想从页面的某个部分中删除任何空元素(即仅在某些div 元素中);您可以为该元素添加一个 id,然后使用选择器 #id *:empty,这意味着该元素中的任何 id 为 id 的空元素。

          这几乎肯定是你想要的。 从技术上讲,一些重要的标签(例如&lt;meta&gt; 标签、&lt;br&gt; 标签、&lt;img&gt; 标签等)是“空的”;因此,如果不指定范围,您最终会删除一些您可能关心的标签。

      • forEach 循环遍历生成的NodeList 中的每个元素,并在其上运行匿名函数(x)=&gt;{x.remove()}x 是列表中的当前元素,对其调用 .remove() 会从 DOM 中删除该元素。

      希望这对某人有所帮助。看到 JavaScript 在短短 8 年内取得了多么大的进步,真是令人惊讶。从几乎总是需要一个库来以简洁的方式编写像这样复杂的东西到能够在本地这样做。

      编辑

      所以,上面详述的方法在大多数情况下都可以正常工作,但它有两个问题:

      • &lt;div&gt; &lt;/div&gt; 这样的元素不会被视为:empty(不是中间的空格)。 CSS 级别 4 选择器通过引入 :blank 选择器解决了这个问题(除了忽略空白之外,它就像是空的),但目前只有 Firefox 支持它(以供应商前缀的形式)。
      • 自动关闭标签被:empty 捕获-:blank 也将保持这种情况。

      我写了一个稍微大一点的函数来处理这两个用例:

      document.querySelectorAll("*").forEach((x)=>{
          let tagName = "</" + x.tagName + ">";
          if (x.outerHTML.slice(tagName.length).toUpperCase() == tagName
              && /[^\s]/.test(x.innerHTML)) {
              x.remove();
          }
      });
      

      我们遍历页面上的每个元素。我们获取该元素的标签名称(例如,如果该元素是一个 div,这将是 DIV,并使用它来构造一个结束标签 - 例如 &lt;/DIV&gt;

      该标签的长度为 6 个字符。我们检查元素 HTML 的大写最后 6 个字符是否匹配。如果是,我们继续。如果没有,则该元素没有结束标记,因此必须是自关闭的。这比列表更可取,因为这意味着如果将新的自闭合标签添加到规范中,您无需更新任何内容。

      然后,我们检查元素的内容是否包含任何空格。 /[^\s]/ 是一个正则表达式。 [] 是 RegEx 中的一个集合,将匹配其中出现的任何字符。如果^ 是第一个元素,则集合变为否定 - 它将匹配不在集合中的任何元素。 \s 表示空格 - 制表符、空格、换行符。所以[^\s] 说的是“任何不是空格的字符”。

      与之相匹配,如果标签不是自闭合的,并且其内容包含非空白字符,那么我们将其删除。


      当然,这比以前的单线要大一些,也没有那么优雅。但它应该适用于基本上所有情况。

      【讨论】:

      • 我发现这段代码实际上删除了还需要的未闭合标签,如链接和元。这实际上是一个不错的“单线”,但它在 html 上有点粗糙。试图找到一个调整来解决这个问题。加一个绝对是为了简单。
      • @Le-Nerdtm 我在帖子中添加了一个编辑,应该可以解决这些问题。
      【解决方案7】:

      这是一个贪婪的正则表达式问题。试试这个:

      str=str.replace(/&lt;[\^&gt;]+&gt;&lt;\/[\S]+&gt;/gim, "");

      str=str.replace(/&lt;[\S]+?&gt;&lt;\/[\S]+&gt;/gim, "");

      在您的正则表达式中,&lt;[\S]+?&gt; 匹配 &lt;i&gt;italic&lt;/i&gt;&lt;\/[\S]+&gt; 匹配 &lt;/p&gt;

      【讨论】:

      • 我知道缺少什么了..谢谢
      【解决方案8】:

      你可以用这个 text = text.replace(/&lt;[^/&gt;][^&gt;]<em>&gt;\s</em>&lt;/[^&gt;]+&gt;/gim, "");

      【讨论】:

        【解决方案9】:

        在代码笔上找到了这个: jQuery 虽然可以完成这项工作

        $('element').each(function() {
          if ($(this).text() === '') {
            $(this).remove();
          }
        });
        

        您需要更改元素以指向要删除空标签的位置。不要指向文档,因为它会导致我在 Toastrackenigma 的回答

        【讨论】:

          【解决方案10】:

          用cheerio will 删除空标签,同时删除图片:

            $('*')
              .filter(function(index, el) {
                return (
                  $(el)
                    .text()
                    .trim().length === 0
                )
              })
              .remove()
          

          用cheerio删除空标签,同时保留图片:

            $('*')
              .filter(function(index, el) {
                return (
                  el.tagName !== 'img' &&
                  $(el).find(`img`).length === 0 &&
                  $(el)
                    .text()
                    .trim().length === 0
                )
              })
              .remove()
          

          【讨论】:

            【解决方案11】:
            <([^>]+)\s*>\s*<\/\1\s*>
            
            <div>asdf</div>
            <div></div> -- will match only this
            <div></notdiv>
            -- and this
            <div  >  
                </div   >
            

            试试自己https://regexr.com/

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-12-13
              • 2020-07-05
              • 2012-04-11
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-11-12
              • 2014-10-08
              相关资源
              最近更新 更多