如何执行一系列字符串替换并能够轻松撤消它们?

时间:2012-05-13 05:08:26

标签: perl sed awk str-replace

我有一系列字符串,它们的替换用空格分隔:

a123 b312
c345 d453

我想将左列中的字符串替换为右列中的字符串,稍后撤消替换。对于第一部分,我可以构造一个sed命令s / ... / ...; s / ... / ...但不考虑反转,它需要我显着改变输入,这需要时间。有没有方便的方法呢?

列出了一些示例程序,可以为win / lin免费提供任何内容。

2 个答案:

答案 0 :(得分:1)

文本编辑器提供“撤消”功能,但命令行实用程序不提供。您可以编写一个脚本来进行替换,然后反转替换文件以反向执行相同的操作。

这是一个脚本,它在'replacements.txt'中进行了一系列替换,并根据脚本的输入运行它们:

#!/usr/bin/perl -w

use strict;

open REPL, "<replacements.txt";
my @replacements;
while (<REPL>) {
    chomp;
    push @replacements, [ split ];
}
close REPL;

while (<>) {
    for my $r (@replacements) { s/$r->[0]/$r->[1]/g }
    print;
}

如果您将此文件另存为“repl.pl”,并将上面的文件另存为“replacements.txt”,则可以像这样使用:

perl repl.pl input.txt >output.txt

要将替换文件转换为'reverse-replacements.txt'文件,您可以使用简单的awk命令:

awk '{ print $2, $1 }' replacements.txt >reverse-replacements.txt

然后只需修改Perl脚本以使用反向替换文件而不是前向文件。

答案 1 :(得分:0)

use strict;
use warnings;

unless (@ARGV == 3) {
    print "Usage: script.pl <reverse_changes?> <rfile> <input>\n";
    exit;
}
my $reverse_changes = shift;
my $rfile = shift;
open my $fh, "<", $rfile or die $!;
my %reps  = map split, <$fh>;

if ($reverse_changes) {
    %reps = reverse %reps;
}

my $rx = join "|", keys %reps;

while (<>) {
    s/\b($rx)\b/$reps{$1}/g;
    print;
}

围绕替换的单词边界检查\b将阻止部分匹配,例如将a12345替换为b31245。在$rx中,您可能希望转义元字符,如果替换中存在元字符。

<强>用法:

执行替换:

script.pl 0 replace.txt input.txt > output.txt

要撤消更改:

script.pl 1 replace.txt output.txt > output2.txt