Evi*_*ady 2 regex perl replace
我有一个包含多个XML标签的文件,如下所示:
<Good>Yay!</Good>
<Great>Yup!</Great>
<Bad>booo</Bad>
<Bad>
<Ok>not that great</ok>
</Bad>
<Good>Wheee!</Good>
Run Code Online (Sandbox Code Playgroud)
我想摆脱"坏"标签和其他任何东西.所以它会变成:
<Good>Yay!</Good>
<Great>Yup!</Great>
<Good>Wheee!</Good>
Run Code Online (Sandbox Code Playgroud)
我知道这个单行:
perl -pe "undef $/;s/<Bad>.*?<\/Bad>//msg" < originalFile > newlyStrippedFile
Run Code Online (Sandbox Code Playgroud)
似乎做我想做的一切(除了添加额外的换行符,但希望我能够轻松地处理它)
但是我需要把它放在一个脚本中(两个文件被读入命令行,一个带有所有标签,另一个带有要拔出的标签列表),所以同样的事情会被多次调用.
而我只是遇到了麻烦.要么它只读一行,要么我得错误或两者兼而有之.
以下是我最近尝试的相关部分:
open ORIGINAL_FILE, $sdb_pathname
or die "Can't open '$sdb_pathname' : $!";
@sdb_input_array = <ORIGINAL_FILE>;
close ORIGINAL_FILE;
@sdb_input_scalar=join("",@sdb_input_array);
foreach $tag (@tags) {
&remove_tag($tag);
}
sub remove_tag
{
my($current_tag) = @_;
$sdb_input_scalar =~ s/<$current_tag>.*?<\/$current_tag>//msg;
open NEWLY_STRIPPED_FILE, $clean_sdb_pathname
or die "Can't open '$clean_sdb_pathname' : $!";
print(NEWLY_STRIPPED_FILE $sdb_input_scalar);
close(NEWLY_STRIPPED_FILE);
}
Run Code Online (Sandbox Code Playgroud)
这让我"在我的$ sdb_input_scalar =〜行中使用未初始化的值$ sdb_input_scalar替换(s ///).并且仅为输入打开Filehandle NEWLY_STRIPPED_FILE
当然,我的两个文件看起来仍然相同,好像我没有对他们做任何事情.
对不起,如果我遗漏了一些明显的东西,但我对perl来说真的很陌生.有人在工作时给出了8小时的估计来完成这个脚本,我已经用了超过5个小时来安装perl,学习语法并让其他方面正确.我知道有一个XML :: Parser模块,但我发现这些例子在我完成的短时间内非常压倒性.
我必须假设我的正则表达式是正确的,因为单线程工作得非常好.谁能帮助我适应我需要的东西?
你真的应该使用XML解析器.这几乎可以保证XML文件不会像你期望的那样解析正则表达式.但是,让我们先开始吧.
你在哪里:
@sdb_input_scalar=join("",@sdb_input_array);
Run Code Online (Sandbox Code Playgroud)
你真的想要:
$sdb_input_scalar=join("",@sdb_input_array);
Run Code Online (Sandbox Code Playgroud)
现在一些其他提示.
在脚本的顶部,确保使用-w标志启用警告,如下所示:
#!/path/to/perl -w
use strict;
Run Code Online (Sandbox Code Playgroud)
一旦你加入use strict它会导致你的几个错误,但这是一件好事.我们将强制执行一些范围和其他良好实践.您现在需要使用my初始化变量(以$,@或%开头).例如:
my @sdb_input_array = <ORIGINAL_FILE>;
Run Code Online (Sandbox Code Playgroud)
要么:
foreach my $tag (@tags) { ... }
Run Code Online (Sandbox Code Playgroud)
不要像你一样打开电话,而是使用三个争论版本:
open ($originalFile, "<", $sdb_pathname)
or die "Can't open '$sdb_pathname' : $!";
my @sdb_input_array = <$originalFile>;
Run Code Online (Sandbox Code Playgroud)
这将把它设置为只读.见http://perldoc.perl.org/functions/open.html
通常你应该避免依赖于全局变量.更改您调用remove_tag()的方式:
foreach $tag (@tags) {
$sdb_input_scalar = remove_tag($sdb_input_scalar, $tag);
}
Run Code Online (Sandbox Code Playgroud)
为了支持这一点,您还需要更改功能:
sub remove_tag
{
my($input, $current_tag) = @_;
$input =~ s/<$current_tag>.*?<\/$current_tag>//msg;
return $input;
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以通过在remove_tag函数之外移动它来迭代所有标记后写出一次:
open ($strippedFile, ">", $clean_sdb_pathname)
or die "Can't open '$clean_sdb_pathname' : $!";
print $strippedFile $sdb_input_scalar;
close($strippedFile);
Run Code Online (Sandbox Code Playgroud)