1

我是 Perl 的新手。我必须在多行中查找和替换。

$content =~ s/<picture[^>]*>(.*?)<\/picture>//gis;

我试过这些代码。我的文件中的所有标签都被替换了。任何人帮助我,我的错误是什么?

我的标签是,

<picture width='960' height='705' baseline='360'>
    <pict-header>
    </pict-header>
</picture>

现在替换为

<picture></picture> 
4

3 回答 3

3

根据我认为你想做的事情,这里是你需要改变的。您的表达式匹配任何<picture>标签直到第一个</picture>标签,无论它是否实际上关闭了您匹配的第一个标签。

假设嵌套<picture>标签是非法的,您需要做的就是<picture></picture>在替换的替换部分添加,例如:

$content =~ s/<picture[^>]*>(.*?)<\/picture>/<picture><\/picture>/gis;

提示:在处理带有斜线的表达式时,请执行以下操作,这样您就不需要转义斜线:

$content =~ s@<picture[^>]*>(.*?)</picture>@<picture></picture>@gis;

这仍然不完美!例如,这个:

<picture stuff="adfgerth"><picture stuff="235wefw45"><somejunk /></picture></picture>

将替换为:

<picture></picture></picture>

但是现在您已经到了一个正则表达式不够用的地步,您可能需要一个 XML 解析器。

于 2012-10-01T14:28:56.573 回答
2

使用 HTML 解析器解析 HTML 可以省去很多麻烦:

#!/usr/bin/env perl

use strict; use warnings;
use HTML::TokeParser::Simple;

die "Need filename\n" unless @ARGV == 1;
my ($filename) = @ARGV;

my $parser = HTML::TokeParser::Simple->new(file => $filename);

while (my $token = $parser->get_token) {
    if ($token->is_start_tag('picture')) {
        $parser->get_tag('/picture');
        print "<picture></picture>";
    }
    else {
        print $token->as_is;
    }
}
于 2012-10-02T15:37:17.937 回答
1

Sinan 的回答有效,但更好的解决方案可能是使用 DOM 解析器,例如Mojo::DOM(它是Mojolicious框架的一部分)。然后你可以做一些非常简单的操作,比如

#!/usr/bin/env perl

use strict;
use warnings;

use Mojo::DOM;

my $content = <<'END';
<picture width='960' height='705' baseline='360'>
    <pict-header>
    </pict-header>
</picture>
END

my $dom = Mojo::DOM->new($content);

$dom->at('picture')->replace('<picture></picture>')->root;

print $dom;
于 2012-10-02T17:38:40.060 回答