【发布时间】:2008-12-19 14:15:13
【问题描述】:
在一个项目中,我们的文本文件如下所示:
mv A, R3
mv R2, B
mv R1, R3
mv B, R4
add A, R1
add B, R1
add R1, R2
add R3, R3
add R21, X
add R12, Y
mv X, R2
我需要根据以下替换字符串,但我正在寻找 寻求更通用的解决方案。
R1 => R2
R2 => R3
R3 => R1
R12 => R21
R21 => R12
我知道我可以在 Perl 中做到这一点,下面代码中的 replace() 函数, 但是真正的应用程序是用Java编写的,所以解决方案需要是 在 Java 中也是如此。
#!/usr/bin/perl
use strict;
use warnings;
use File::Slurp qw(read_file write_file);
my %map = (
R1 => 'R2',
R2 => 'R3',
R3 => 'R1',
R12 => 'R21',
R21 => 'R12',
);
replace(\%map, \@ARGV);
sub replace {
my ($map, $files) = @_;
# Create R12|R21|R1|R2|R3
# making sure R12 is before R1
my $regex = join "|",
sort { length($b) <=> length($a) }
keys %$map;
my $ts = time;
foreach my $file (@$files) {
my $data = read_file($file);
$data =~ s/\b($regex)\b/$map{$1}/g;
rename $file, "$file.$ts"; # backup with current timestamp
write_file( $file, $data);
}
}
您对 Java 实现的帮助将不胜感激。
【问题讨论】:
-
为什么在制作正则表达式之前对键进行排序?
-
所以 R12 将在 R1 之前匹配(否则 R12 将永远不会匹配),现在代码中也添加了注释。
-
对它们进行排序并不是真正的解决方案;如果文本包含“R13”,它将更改为“R23”。您希望正则表达式与您告诉它的内容相匹配,仅此而已。在这种情况下,单词边界会这样做: /\b(R1|R2|R3|R12|R21)\b/
-
你是对的,在正则表达式周围添加 \b 将确保应该单独保留的 R122 与 R12 不匹配并更改为 R212