【问题标题】:How can I remove an entire HTML tag (and its contents) by its class using a regex?如何使用正则表达式按其类删除整个 HTML 标记(及其内容)?
【发布时间】:2010-09-18 14:24:34
【问题描述】:

我不太擅长正则表达式,但我正在学习。

我想通过类名删除一些 html 标记。这是我到目前为止所拥有的:

<div class="footer".*?>(.*?)</div>

第一个 .*?是因为它可能包含其他属性,其次是它可能包含其他 html 内容。

我做错了什么?我试了很多套都没有成功。

更新

在 DIV 内部,它可以包含多行,我正在使用 Perl 正则表达式。

【问题讨论】:

  • 你使用什么目标语言?
  • 我添加了 Perl,但我可能在 C# 中需要它

标签: html regex perl filter


【解决方案1】:

正如其他人所说,使用正则表达式处理 HTML 是出了名的棘手,而 DOM 方法可能会更好。例如:

use HTML::TreeBuilder::XPath;

my $tree = HTML::TreeBuilder::XPath->new;
$tree->parse_file( 'yourdocument.html' );

for my $node ( $tree->findnodes( '//*[@class="footer"]' ) ) {
    $node->replace_with_content;   # delete element, but not the children
}

print $tree->as_HTML;

【讨论】:

  • 要删除元素及其子元素,请将 'replace_with_content' 替换为 'detach'。
【解决方案2】:

您还需要在 div 标签中允许在上课前进行其他操作

<div[^>]*class="footer"[^>]*>(.*?)</div>

另外,不区分大小写。您可能需要转义引号或结束标记中的斜线等内容。你在什么背景下做这个?

还请注意,使用正则表达式解析 HTML 可能非常讨厌,具体取决于输入。下面的答案提出了一个很好的观点 - 假设您的结构如下:

<div>
    <div class="footer">
        <div>Hi!</div>
    </div>
</div>

试图为此构建正则表达式是灾难的根源。最好的办法是将文档加载到 DOM 中,然后对其执行操作。

应该紧密映射到 XML::DOM: 的伪代码:

document = //load document
divs = document.getElementsByTagName("div");
for(div in divs) {
    if(div.getAttributes["class"] == "footer") {
        parent = div.getParent();
        for(child in div.getChildren()) {
            // filter attribute types?
            parent.insertBefore(div, child);
        }
        parent.removeChild(div);
    }
}


这是一个 perl 库 HTML::DOM 和另一个 XML::DOM
.NET 具有处理 dom 解析的内置库。

【讨论】:

  • 当所有 html 在同一行时有效,但在缩进时无效。为什么 [^>] in : "footer"[^>]?
  • 使正则表达式具有确定性。大多数引擎可以毫无问题地处理不确定性,但有时会产生意想不到的结果。从技术上讲,[^>] 和 [c] 之间仍然存在不确定性问题,但并不那么重要。
  • 寻找任何不是右括号的东西
【解决方案3】:

在 Perl 中,您需要 /s 修饰符,否则点将不匹配换行符。

也就是说,使用适当的 HTML 或 XML 解析器来删除 HTML 文件中不需要的部分更为合适。

【讨论】:

    【解决方案4】:
    <div[^>]*class="footer"[^>]*>(.*?)</div>
    

    为我工作,但需要在特殊字符前使用反斜杠

    <div[^>]*class=\"footer\"[^>]*>(.*?)<\/div>
    

    【讨论】:

      【解决方案5】:

      部分取决于您使用的确切正则表达式引擎 - 哪种语言等。但一种可能性是您需要转义引号和/或正斜杠。您可能还希望使其不区分大小写。

      <div class=\"footer\".*?>(.*?)<\/div>
      

      否则请说明您使用的是什么语言/平台 - .NET、java、perl ...

      【讨论】:

      • 请注意,这里需要 /s 选项,因为其中一些字符可能是换行符。
      【解决方案6】:

      试试这个:

      <([^\s]+).*?class="footer".*?>([.\n]*?)</([^\s]+)>
      

      您最大的问题是嵌套标签。例如:

      <div class="footer"><b></b></div>
      

      给出的正则表达式将通过&lt;/b&gt; 匹配所有内容,而&lt;/div&gt; 则悬空。您必须假设您要查找的标签没有嵌套元素,或者您需要使用某种从 HTML 到 DOM 的解析器和 XPath 查询来删除整个子树。

      【讨论】:

      • 您可以在正则表达式末尾的第一个捕获的组上使用反向引用...
      • 给定的正则表达式与中间标签不匹配。 div 标签内的惰性量词将在 div 末尾的 > 处停止匹配。因此,我认为粗体标签将与 (.*?) 匹配。
      • 嗯,好吧,它要么太懒,要么太贪婪。另一个答案给出了一个贪婪地匹配一个 many 结束标签的例子。正则表达式对于这类事情还不够强大。
      【解决方案7】:

      由于正则表达式的贪婪,这将是棘手的,(请注意,我的示例可能特定于 perl,但我知道贪婪是 RE 的普遍问题。)第二个 @987654321 @ 将尽可能匹配&lt;/div&gt; 之前,所以如果你有以下:

      &lt;div class="SomethingElse"&gt;&lt;div class="footer"&gt; stuff &lt;/div&gt;&lt;/div&gt;

      表达式将匹配:

      &lt;div class="footer"&gt; stuff &lt;/div&gt;&lt;/div&gt;

      这可能不是你想要的。

      【讨论】:

        【解决方案8】:

        为什么不&lt;div class="footer".*?&lt;/div&gt; 我也不是正则表达式专家,但我认为您不需要为打开的 div 标签指定最后一个括号

        【讨论】:

        • 也许他想抓取 div 的内容?
        • 是的,他说他想删除标签,而不是内容。
        • 该正则表达式将捕获整个网页的第一个
        猜你喜欢
        • 2010-09-12
        • 2013-07-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-26
        相关资源
        最近更新 更多