Perl:如何替换这个字符串序列

时间:2013-07-10 08:53:45

标签: perl substitution

我需要替换以下字符串:

<book name=""
      author="">

<magazine>

我的代码不起作用:

sub substitution
{
my $find = "book name\=\"\"\nauthor\=\"\"";
my $replace = "magazine";
{  
local @ARGV = ("$_[0]");
local $^I = '.bac';

while( <> )
{
  if( s/$find/$replace/ig ) {
     print;
                            }

else {
     print;
     }
} //while
}

4 个答案:

答案 0 :(得分:3)

就像Brian已经说过的那样,使用XML解析器。下面是一个使用XML :: LibXML并使用setNodeName(用于更改元素名称)和removeAttributes(用于删除这两个属性)进行DOM操作的示例:

use strict;
use XML::LibXML;

my $doc = XML::LibXML->new->parse_string(<<EOF);
<books>
 <book name=""
       author="">
  <chapter>something</chapter>
 </book>
 <book name=""
       author="">
  <chapter>something</chapter>
 </book>
</books>
EOF

for my $book_node ($doc->findnodes('//book')) {
    $book_node->setNodeName('magazine');
    $book_node->removeAttribute($_) for qw(name author);
}

print $doc->serialize;

另一种可能性是在这里使用xslt ......

答案 1 :(得分:1)

强烈建议您使用XML parser而非正则表达式well-documented reasons

查看Comprehensive Perl Archive Network以获取更合适的库。

答案 2 :(得分:1)

如果您想要快速简便的解决方案(为什么还要使用Perl?),那么只需使用

my $find = qr|<book name=""\s+author="">|s;
my $replace = '<magazine>';

因为你想要在多行中替换某些东西,你不能逐行读取,而应该在标量中篡改文件(如果你的文件足够小以适应内存)

local $/; # undefines input lines separator
# open your file with open(FILE, '<', $filename);
my $text = <FILE>;
$text =~ s/$find/$replace/g;
# do with $text what you want now, print it or anything
# don't forget to close your FILE

这很快,很脏,但效果很好。如果您的文件不适合内存,或者您想确保一切正常,请使用XML解析器,但请记住

  1. 不要使用XML :: Simple,它已经坏了,真的
  2. 对于大型文件,您需要流式XML解析器,例如XML::Parser

答案 3 :(得分:1)

使用xshXML::LibXML的包装:

open file.xml ;
for //book[@name="" and @author=""] {
    rename magazine . ;
    delete @* ;
}
save :b ;