Regex 使用perl搜索和替换文件夹中的多个xml文件

Regex 使用perl搜索和替换文件夹中的多个xml文件,regex,xml,perl,replace,Regex,Xml,Perl,Replace,我刚刚进入perl世界,我得到了一个任务,用perl替换文件夹中的多个xml文件,我尝试了一些perl单行代码,但没有帮到我,我需要一个perl代码来替换选定文件夹中的多个文本文件。我从stackoverflow尝试了下面这篇文章,但也没有帮到我。请温柔,因为我是新的,我提供了我的试用代码从上面的stackflow后显示错误,请查看并建议解决方案 my $dir = ***D:\Perl***; my $d = opendir(); map { if ( -f "$dir

我刚刚进入perl世界,我得到了一个任务,用perl替换文件夹中的多个xml文件,我尝试了一些perl单行代码,但没有帮到我,我需要一个perl代码来替换选定文件夹中的多个文本文件。我从stackoverflow尝试了下面这篇文章,但也没有帮到我。请温柔,因为我是新的,我提供了我的试用代码从上面的stackflow后显示错误,请查看并建议解决方案

my $dir = ***D:\Perl***;
my $d = opendir();
map {
    if (
        -f "$dir/$_"
        && ($_ =~ "\.xml$")
    ) {
        open (my $input_file, '<', ) or die "unable to open $input_file $!\n";

        my $input;
        {
            local $/;               #Set record separator to undefined.
            $input = <$input_file>; #This allows the whole input file to be read at once.
        }
        close $input_file;

        $input =~ s/Comment//g;

        open (my $output_file, '>', "$dir/$_") or die "unable to open $output_file $!\n";
        print {$output_file} $input;

        close $output_file or die $!;
    }
} readdir($d);
closedir($d);
XML文件位于文件夹D:\Perl中\

1.xml
2.xml
3.xml
每个xml文件中的代码如下所示

<?xml version="1.0">
<root>
<!--This is my comment line 1-->
<subtag>
<element>This is 1.xml file</element>
</subtag>
</root>

这是一个1.xml文件

作为Perl的新手,我印象深刻,您已经掌握了
map
map
旨在将数组转换为哈希,它可以通过计算代码块来实现这一点

然而,这是相当讨厌的,因为它创建的代码很难遵循。为什么不改为使用
for
(或
foreach
)循环?关键的警告标志是“我是否将map的结果分配给hash(或hashref)?”如果答案是否定的,那么很可能这不是一个好的方法

另外:对于这种类型的迭代操作,我倾向于选择
glob
而不是
opendir

但最重要的是:

不要对XML使用正则表达式和基于行的解析 请,请,请使用XML解析器来解析XML。通过正则表达式这样做是令人讨厌的——它会使脆弱的代码变得不可靠。XML规范中有很多东西使得语义相同的XML(因此从上游系统的角度来看是“有效的”)与正则表达式不匹配。例如一元标记、换行和跨行拆分标记

例如:

<XML
><some_tag
att1="1"
att2="2"
att3="3"
></some_tag></XML>
无论如何,记住这一点-回答您的问题:

从某些XML中删除注释 这将把示例XML转换为:

<?xml version="1.0"?>
<root>
  <subtag>
    <element>This is 1.xml file</element>
  </subtag>
</root>
注意-这将删除每个元素标记-您可以通过xpath表达式(例如,
'subtag/element'
)或使用适当的子例程来处理和解析以下内容,从而应用更具选择性的条件:

sub delete_element_with_file {
    my ( $twig, $element ) = @_;
    if ( $element->text =~ m/file/ ) { $element->delete }
}


my $twig = XML::Twig->new(
    pretty_print  => 'indented_a',
    twig_handlers => { 'subtag/element' => \&delete_element_with_file }
);

##etc. 

你到底想替换什么?替换所有xml文件中的特定标记,例如,我正在从所有xml文件中删除为什么我最近看到了
map
而不是
foreach
的用法?感谢你的鼓励,我只是一个初学者,不是一个完美的程序员,我从互联网上获得了代码并尝试过。请告诉我,我不知道你怎么猜的.谢谢你的评论。
<XML>
  <some_tag
      att1="1"
      att2="2"
      att3="3"></some_tag>
</XML>
<XML>
  <some_tag att1="1" att2="2" att3="3"></some_tag>
</XML>
<XML>
  <some_tag att1="1" att2="2" att3="3"/>
</XML>
<?xml version="1.0"?>
#!/usr/local/bin/perl
use strict;
use warnings;

use XML::Twig;

foreach my $file ( glob("$dir/*.xml") ) {
    my $twig =
        XML::Twig->new( comments => 'drop', pretty_print => 'indented_a' );
    $twig->parsefile($file);
    open( my $output, ">", $file . ".new" ) or warn $!;
    print {$output} $twig->sprint;
    close($output);
}
<?xml version="1.0"?>
<root>
  <subtag>
    <element>This is 1.xml file</element>
  </subtag>
</root>
XML::Twig->new( pretty_print => 'indented_a',
                twig_handlers => { 'element' => sub { $_ -> delete } } );
sub delete_element_with_file {
    my ( $twig, $element ) = @_;
    if ( $element->text =~ m/file/ ) { $element->delete }
}


my $twig = XML::Twig->new(
    pretty_print  => 'indented_a',
    twig_handlers => { 'subtag/element' => \&delete_element_with_file }
);

##etc.