大约有100个文件,我需要浏览每个文件并删除<style>
和</style>
之间的所有数据+删除这些标记。
例如
<html>
<head> <title> Example </title> </head>
<style>
p{color: red;
background-color: #FFFF;
}
div {......
...
}
</style>
<body>
<p> hi I'm a paragraph. </p>
</body>
</html>
应该成为
<html>
<head> <title> Example </title> </head>
<body>
<p> hi I'm a paragraph. </p>
</body>
</html>
此外,在某些文件中,样式模式类似于
<style type="text/css"> blah </style>
或
<link rel="stylesheet" type="text/css" href="$url_path/gridsorting.css">
我需要删除所有3种模式。我如何在Perl中执行此操作?
答案 0 :(得分:6)
use strict;
use warnings;
use XML::LibXML qw( );
my $qfn = 'a.html';
my $doc = XML::LibXML->load_html( location => $qfn );
my $root = $doc->documentElement();
for my $style_node ($root->findnodes('//style')) {
$style_node->parentNode()->removeChild($style_node);
}
{
open(my $fh, '>', $qfn)
or die;
print($fh $doc->toStringHTML());
}
它正确处理:
截至本次更新时,其他解决方案仅处理其中的2个或3个。
答案 1 :(得分:4)
Ikegami是对的,你真的应该使用至少一个HTML / XML解析器来完成这个任务。我个人喜欢使用Mojo::DOM
解析器。这是HTML的文档 - 对象模型接口,它支持CSS3 selectors,使您在需要时非常灵活。这对于它来说非常简单:
#!/usr/bin/env perl
use strict;
use warnings;
use Mojo::DOM;
my $content = <<'END';
<html>
<head> <title> Example </title> </head>
<style>
p{color: red;
background-color: #FFFF;
}
div {......
...
}
</style>
<body>
<p> hi I'm a paragraph. </p>
</body>
</html>
END
my $dom = Mojo::DOM->new( $content );
$dom->find('style')->pluck('remove');
print $dom;
pluck
方法有点令人困惑,但它实际上只是在每个结果对象上执行方法的简写。类似的行可能是
$dom->find('style')->each(sub{ $_->remove });
这更容易理解但不太可爱。
在阅读完你只需处理基本表单的编辑后,我必须进一步强调,这就是为什么你使用解析器修改HTML而不是让你的正则表达式变得荒谬的原因。
现在让我们说$content
变量也包含这些行
<link rel="stylesheet" type="text/css" href="$url_path/gridsorting.css">
<link rel="icon" href="somefile.jpg">
你要删除第一个,而不是第二个。您可以通过以下两种方式之一完成此操作。
$dom->find('link')->each( sub{ $_->remove if $_->{rel} eq 'stylesheet' } );
此机制使用对象方法(以及Mojo :: DOM公开属性作为哈希键)仅删除具有link
的{{1}}标记。但是,您可以将CSS3选择器仅用于rel=stylesheet
这些元素,并且由于Mojo :: DOM具有完整的CSS3选择器支持,您可以执行
find
CSS3选择器语句可以用逗号连接,以查找与两个选择器匹配的所有标签,因此我们可以简单地包含该行
$dom->find('link[rel=stylesheet]')->pluck('remove');
并一举摆脱所有令人反感的样式表!
答案 2 :(得分:2)
另一种可能的解决方案是使用HTML::TreeBuilder
。
#!/usr/bin/perl
use strict;
use warnings;
use HTML::TreeBuilder 5; # Ensure weak references in use
foreach my $file_name (@ARGV) {
my $tree = HTML::TreeBuilder->new; # empty tree
$tree->parse_file($file_name);
# print "Hey, here's a dump of the parse tree of $file_name:\n";
# $tree->dump; # a method we inherit from HTML::Element
foreach my $e ($tree->look_down(_tag => "style")) {
$e->delete();
}
foreach my $e ($tree->look_down(_tag => "link", rel => "stylesheet")) {
$e->delete();
}
print "And here it is, bizarrely rerendered as HTML:\n",
$tree->as_HTML, "\n";
# Now that we're done with it, we must destroy it.
$tree = $tree->delete; # Not required with weak references
}
答案 3 :(得分:1)
使用sed
的一种方式:
sed '/<style>/,/<\/style>/d' file.txt
结果:
<html>
<head> <title> Example </title> </head>
<body>
<p> hi I'm a paragraph. </p>
</body>
</html>
答案 4 :(得分:0)
perl -lne 'print unless(/<style>/.../<\/style>/)' your_file
测试如下:
> cat temp
<html>
<head> <title> Example </title> </head>
<style>
p{color: red;
background-color: #FFFF;
}
div {......
...
}
</style>
<body>
<p> hi I'm a paragraph. </p>
</body>
</html>
> perl -lne 'print unless(/<style>/.../<\/style>/)' temp
<html>
<head> <title> Example </title> </head>
<body>
<p> hi I'm a paragraph. </p>
</body>
</html>
>
如果你想在原地进行,那么:
perl -i -lne 'print unless(/<style>/.../<\/style>/)' your_file
答案 5 :(得分:0)
我想出了一种方法,你可以尝试以下方法:
#! /usr/bin/perl -w
use strict;
my $line = << 'END';
<html>
<head> <title> Example </title> </head>
<style>
p{color: red;
background-color: #FFFF;
}
div {......
...
}
</style>
<body>
<p> hi I'm a paragraph. </p>
</body>
</html>
END
$line =~ s{<style[^>]*.*?</style>.}{}gs;
print $line;