假设我想在文本文件中将所有 AAA 替换为 BBB,将所有 BBB 替换为 AAA。
看起来明显的解决方案(在 Perl 或 Sed 中)是:
s/AAA/BBB/g;s/BBB/AAA/g;
但这不起作用,因为在用 BBB 替换 AAA 后,还可以将其替换回 AAA。
有哪些解决方案可以解决这一问题?
也许您可以提供一些 Perl(或 Python 或其他)代码?
答案1
哦,我发现了一个可以做到这一点的模块:
perl -MReplaceMultiple -e ‘打印 replace_multiple({“AAA”=>“BBB”, “BBB”=>“AAA”}, “AAABBB”), “\n”;’
ReplaceMultiple.pm:
包ReplaceMultiple; 使用严格; 使用警告; 我们的(@ISA,@EXPORT); 需要出口商;@ISA = qw(出口商); @EXPORT = qw(replace_multiple_inplace 替换多个); 子替换_多个_就地{ 我的($hash,$str_ref)= @_; 我的 $obj = ReplaceMultiple->new($hash); 返回 $obj->apply_inplace($str_ref); } 子替换多个{ 我的($hash,$str)= @_; 我的 $obj = ReplaceMultiple->new($hash); 返回 $obj->apply($str); } 子新{ 我的($class,$hash)= @_; 我的 $re_str = "(" . (join '|', map { "\Q$_\E" } keys %$hash) . ")"; 我的 $self = 祝福 {HASH=>$hash, RE=>qr/$re_str/}, $class; 返回$self; } 子应用_就地{ 我的($self,$str_ref)=@_; $$str_ref =~ s/$self->{RE}/$self->{HASH}{$1}/g; 返回 $$str_ref; } 子应用{ 我的($self,$str)=@_; 我的 $str2 = $str; 返回 $self->apply_inplace(\$str2); } 1;
答案2
在 Perl 中,你可以使用标志/e
来埃在替换的替换部分中评估代码:
s/(AAA|BBB)/'AAA' eq $1 ? 'BBB' : AAA/ge
解释:
(AAA|BBB)
匹配 AAA 或 BBB 并将匹配的字符串保存在 $1 中。condition ? true : false
是“三元运算符”。如果“条件”为真,则返回“真”值,否则返回“假”。因此,在本例中,它返回用于替换的字符串。/ge
意思是“全局”,即每行不只一次,以及“eval”,即将替换部分理解为要运行的代码。