我遇到需要搜索以下字符串模式的情况,并通过插入新字符串和新行来修改它们。
e.g。
搜索以下模式:
<start_date>2015-07-21T23:16:13Z</start_date>
<Exec>
并替换为
</start_date>\n</Compilation>\n<Exec>
所以这是我使用的不起作用的命令:
perl -i.bak -p -e 's#\<\/start_date\>\\n\<Exec\>#\<\/start_date\>\\n\<\/Compilation\>\\n\<Exec\>#gi'
还有更好的方法吗?请指出我在哪里做错了。
编辑:我尝试使用代码而不是一个指挥官,但仍无法正常工作:
#!usr/bin/perl
my $file = <*.xml>;
open (XML, "<$file") || die "file dose not exist\n";
open (NXML, ">nfile");
my @lines =<XML>;
foreach my $line (@lines) {
$line =~ s|<start_date>.*</start_date>\n<Exec>|</start_date>\n</Compilation>\n<Exec>|ms;
print NMXL $line;
}
close XML;
close NMXL;
unlink ("$file");
rename ("nfile", $file);
unlink ("nfile");
以下代码效果很好:@buff @TLP,非常感谢您的支持。我真的从你们那里学到了有价值的信息。
$/ = undef; # buff's suggestion.
open (XML, "<$file");
open (NXML, ">file");
my @lines=<XML>;
foreach my $line (@lines) {
$line =~ s/(PC\d+")/$1 tag="$tagname"/gi;
$line =~ s#</start_date>\n<Exec>#</start_date>\n</Compilation>\n<Exec>#gi; # buff's suggestion.
print NXML $line;
}
答案 0 :(得分:2)
您的方法存在一些问题:
您正在使用perl -p
逐行读取输入并将代码应用于每一行。因此,您尝试将一行与多行模式匹配。你可以啜饮整个文件并像这样使用它:
perl -e '
$/ = undef;
my $string = <>;
#here you modify the string
print $string' < input_file > modified_file
你的正则表达式是错误的:要匹配输入,你需要这样的东西:
s|<start_date>.*</start_date>\n<Exec>|</start_date>\n</Compilation>\n<Exec>|gi
这可以做你想写的内容,但我怀疑你只想用</start_date>
取代</start_date>\n</Compilation>
。如果是这种情况,这可能适合您:
perl -i.bak -p -e 's#</start_date>#</start_date>\n</Compilation>#;'
如果您只想替换</start_date>
后跟<Exec>
,请在评论中使用带有slurp的变体和@TLP提供的正则表达式:
perl -e '
$/ = undef;
my $string = <>;
$string =~ s#</start_date>\n<Exec>#</start_date>\n</Compilation>\n<Exec>#gi;
print $string' < input_file > modified_file
或将其另存为脚本(例如fixxml.pl):
#!/usr/bin/env perl
use strict;
use warnings;
$/ = undef;
my $string = <>;
$string =~ s#</start_date>\n<Exec>#</start_date>\n</Compilation>\n<Exec>#gi;
print $string;
然后将其作为perl fixxml.pl input.xml > output.xml
最后,如果可能的话,使用适当的XML库。