我是perl的新手。看到了许多样本,但在编写解决方案时遇到了问题 我有一个字符串列表,每个字符串应该用不同的字符串a-> a2,b-> b34等替换。替换列表在某些csv文件中。需要递归地对目录中的所有文件执行此替换。 可能是任何其他语言,只是认为perl将是最快的
答案 0 :(得分:4)
您的问题可以分为三个步骤:
让我们做一个倒计时,看看我们如何做到这一点:)
#!/usr/bin/perl
use strict; use warnings;
我们将定义一个子searchAndReplace
。它将文件名作为参数并访问外部哈希。我们将调用此哈希%replacements
。每个键都是我们要替换的字符串,值是替换。这“强加”了每个搜索字符串只能有一个替换的限制,但这看起来很自然。我将进一步假设每个文件都相当小(即适合RAM)。
sub searchAndReplace {
my ($filename) = @_;
my $content = do {
open my $file, "<", $filename or die "Cant open $filename: $!";
local $/ = undef; # set slurp mode
<$file>;
};
while(my ($string, $replacement) = each %replacements) {
$content =~ s/\Q$string\E/$replacement/g;
}
open my $file, ">", $filename or die "Can't open $filename: $!";
print $file $content; # I didn't forget the comma
close $file;
}
这段代码非常简单,我在正则表达式中转义$string
,以便不将内容视为模式。这个实现的副作用是可能替换部分已被替换的$content
字符串,但是如果这是绝对必要的话,可以解决这个问题。
我们将定义一个名为anakinFileWalker
的子组件。它采用文件名或目录名称,searchAndReplace
子作为参数。如果filename参数是普通文件,它会执行searchAndReplace
,如果它是一个目录,它会打开目录并在每个条目上调用自己。
sub anakinFileWalker {
my ($filename, $action) = @_;
if (-d $filename) {
opendir my $dir, $filename or die "Can't open $filename: $!";
while (defined(my $entry = readdir $dir)) {
next if $entry eq '.' or $entry eq '..';
# come to the dark side of recursion
anakinFileWalker("$filename/$entry", $action); # be sure to give full path
}
} else {
# Houston, we have a plain file:
$action->($filename);
}
}
当然,如果你有循环符号链接,这个子组就会爆炸。
%replacements
有一个很好的模块Text::CSV
可以帮助您满足您的所有需求。只需确保%replacements
符合上述定义,但这并不难。
当%replacements
准备好后,我们就这样做了
anakinFileWalker($topDirectory, \&searchAndReplace);
应该工作。如果没有,这应该让你知道如何解决这个问题。