我不太擅长正则表达式,但我正在学习。
我想通过类名删除一些 html 标记。这是我到目前为止所拥有的:
<div class="footer".*?>(.*?)</div>
首先 。*?是因为它可能包含其他属性,第二个是它可能包含其他 html 内容。
我究竟做错了什么?我已经尝试了很多设置但没有成功。
更新
在 DIV 内它可以包含多行,我正在使用 Perl 正则表达式。
正如其他人所说,使用正则表达式处理 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;
您还需要在 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 中,您需要/s
修饰符,否则点将不匹配换行符。
也就是说,使用适当的 HTML 或 XML 解析器来删除 HTML 文件中不需要的部分更为合适。
<div[^>]*class="footer"[^>]*>(.*?)</div>
为我工作,但需要在特殊字符之前使用反斜杠
<div[^>]*class=\"footer\"[^>]*>(.*?)<\/div>
部分取决于您使用的确切正则表达式引擎 - 哪种语言等。但一种可能性是您需要转义引号和/或正斜杠。您可能还想让它不区分大小写。
<div class=\"footer\".*?>(.*?)<\/div>
否则,请说出您使用的语言/平台 - .NET、java、perl ...
试试这个:
<([^\s]+).*?class="footer".*?>([.\n]*?)</([^\s]+)>
您最大的问题将是嵌套标签。例如:
<div class="footer"><b></b></div>
给出的正则表达式将通过 匹配所有内容</b>
,最后留下</div>
悬空。您将不得不假设您要查找的标记没有嵌套元素,或者您将需要使用某种从 HTML 到 DOM 的解析器和 XPath 查询来删除整个子树。
由于正则表达式的贪婪,这将很棘手,(请注意,我的示例可能特定于 perl,但我知道贪婪是 RE 的普遍问题。)第二个.*?
将在 之前尽可能匹配</div>
,所以如果你有以下几点:
<div class="SomethingElse"><div class="footer"> stuff </div></div>
表达式将匹配:
<div class="footer"> stuff </div></div>
这不太可能是您想要的。
为什么<div class="footer".*?</div>
我也不是正则表达式大师,但我认为您不需要为打开的 div 标签指定最后一个括号