我有一个文件和从另一个文件中得到的字符串对的列表。我需要用第二个字符串替换第一个字符串中的第一个字符串,并为每一对执行此操作。 是否有更高效/简单的方法来执行此操作(使用Perl,grep,sed或其他),然后对每对值运行单独的正则表达式替换?如何在Perl中替换另一个子字符串?
回答
#! /usr/bin/perl
use warnings;
use strict;
my %replace = (
"foo" => "baz",
"bar" => "quux",
);
my $to_replace = qr/@{["(" .
join("|" => map quotemeta($_), keys %replace) .
")"]}/;
while (<DATA>) {
s/$to_replace/$replace{$1}/g;
print;
}
__DATA__
The food is under the bar in the barn.
@{[...]}
位可能看起来很奇怪。在quote and quote-like operators内插入生成的内容是一种破解。 join
的结果进入匿名数组引用构造函数[]
,并立即取消引用,这归功于@{}
。
如果一切似乎太wonkish,这是一样的
my $search = join "|" => map quotemeta($_), keys %replace;
my $to_replace = qr/($search)/;
减去临时变量。
请注意使用quotemeta
- 感谢Ivan! - 它转义每对中的第一个字符串,以便正则表达式引擎将它们视为文字字符串。
输出:
The bazd is under the quux in the quuxn.
元编程,也就是说,写写入另一个程序的程序,也不错。开始的时候看起来很熟悉:
#! /usr/bin/perl
use warnings;
use strict;
use File::Compare;
die "Usage: $0 path ..\n" unless @ARGV >= 1;
# stub
my @pairs = (
["foo" => "baz"],
["bar" => "quux"],
['foo$bar' => 'potrzebie\\'],
);
现在我们产生做所有s///
替代品,但is quotemeta
on the replacement side a good idea?程序 -
my $code =
"sub { while (<>) { " .
join(" " => map "s/" . quotemeta($_->[0]) .
"/" . quotemeta($_->[1]) .
"/g;",
@pairs) .
"print; } }";
#print $code, "\n";
与eval
编译:
my $replace = eval $code
or die "$0: eval: [email protected]\n";
要做到我们使用Perl的ready-made in-place editing:
# set up in-place editing
$^I = ".bak";
my @save_argv = @ARGV;
$replace->();
下面是一个额外的精密,恢复备份的File::Compare模块判断一直不必要的:
# in-place editing is conservative: it creates backups
# regardless of whether it modifies the file
foreach my $new (@save_argv) {
my $old = $new . $^I;
if (compare($new, $old) == 0) {
rename $old => $new
or warn "$0: rename $old => $new: $!\n";
}
}
在将它们放入正则表达式之前,您还应该使用'quotemeta'键。 – 2010-09-22 17:36:27
由于我在perl中是一个完整的绿色,你能解释一下这里做了什么吗?具体来说这行:@ {[“(”。join(“|”=> keys%replace)。“)”]} – Artium 2010-09-22 17:50:22
@Artium我被带走了。查看更新的答案。 – 2010-09-22 18:03:22
构建对的哈希。然后将目标字符串拆分为单词标记,并根据散列中的键检查每个标记。如果存在,请用该键的值替换它。
有两种方式,他们都需要您汇编的密钥的正则表达式交替表:
my %table = qw<The A the a quick slow lazy dynamic brown pink . !>;
my $alt
= join('|'
, map { quotemeta } keys %table
sort { (length $b <=> length $a) || $a cmp $b }
)
;
my $keyword_regex = qr/($alt)/;
然后你就可以在取代中使用这个表达式:
my $text
= <<'END_TEXT';
The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog.
The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog.
END_TEXT
$text =~ s/$keyword_regex/$table{ $1 }/ge; # <- 'e' means execute code
或者你可以在一个循环做到这一点:
use English qw<@LAST_MATCH_START @LAST_MATCH_END>;
while ($text =~ /$keyword_regex/g) {
my $key = $1;
my $rep = $table{ $key };
# use the 4-arg form
substr($text, $LAST_MATCH_START[1]
, $LAST_MATCH_END[1] - $LAST_MATCH_START[1], $rep
);
# reset the position to start + new actual
pos($text) = $LAST_MATCH_START[1] + length $rep;
}
如果eval
不是一个安全问题:
eval $(awk 'BEGIN { printf "sed \047"} {printf "%s", "s/\\<" $1 "\\>/" $2 "/g;"} END{print "\047 substtemplate"}' substwords)
这构建了一个长sed
命令由多个替换命令。它可能会超出你的最大命令行长度。它期望单词对文件由每行上由空白分隔的两个单词组成。替换将仅用于整个单词(无替代)。
如果单词对文件包含对sed
有意义的字符,它可能会窒息。
你能做到这样,如果你sed
坚持-e
:
eval $(awk 'BEGIN { printf "sed"} {printf "%s", " -e \047s/\\<" $1 "\\>/" $2 "/g\047"} END{print " substtemplate"}' substwords)
- 1. 替换字符串用另一个子
- 2. 如何在Perl中替换字符串中的一个或多个字符串
- 3. 用另一个词或句子替换字符串中的字
- 4. 替换字符串的子字符串用另一个字符串
- 5. 如何替换字符串发生在另一个字符串的NSMutableString中
- 6. 如何在Perl中的字符串末尾替换字符?
- 7. 用另一个替换字符串
- 8. Perl字符串替换?
- 9. Perl,字符串替换
- 10. 用另一个字符串替换子串rails
- 11. perl搜索并替换一个子字符串
- 12. 用另一个字符串替换字符串的一部分
- 13. 如何用haskell中的另一个替换字符串
- 14. 如何用JavaScript中的另一个字符串替换空格?
- 15. 从一个阵列替换字符到另一个字符串
- 16. PHP如何用另一个字符串替换多个相同的字符串?
- 17. 如何在字符串中随机替换一个字符?
- 18. 如何在一个字符串中递归地替换字符
- 19. 如何在字符串的一个子部分上执行字符串替换?
- 20. 大熊猫:用另一个字符串替换字符串
- 21. 需要用另一个字符串替换部分字符串
- 22. 用另一个字符串替换字符串的第一个字符
- 23. R如何用一个新子串替换较长字符串中的子串
- 24. 在Python中,我该如何做一个字符串替换和回收替换的子字符串?
- 25. 如何在一个字符串变量替换已知子值
- 26. 如何在Android的整个应用程序中用另一个字符串替换一个字符串?
- 27. 替换字符串中的URL - Perl
- 28. Android - 如何用另一个字符串替换部分字符串?
- 29. 访问VBA |如何用另一个字符串替换字符串的部分
- 30. 如何替换字符串中的子字符串
@布赖恩d FOY我不知道那个标题编辑总结准确问题的内容。 – 2010-09-22 22:25:19
如果您有更好的标题,请使用它。原来并不好。 – 2010-09-22 22:32:23