我是 perl 的新手。看到了很多样本,但在编写解决方案时遇到了问题 我有一个字符串列表,每个字符串应该替换为不同的字符串 a->a2、b->b34 等。替换列表在某个 csv 文件中。需要对目录中的所有文件递归执行此替换。可能是任何其他语言,只是认为 perl 是最快的
问问题
1679 次
1 回答
4
您的问题可以分为三个步骤:
- 从 CSV 文件中获取搜索和替换字符串,
- 获取给定目录中所有文本文件的列表,包括。子目录,以及
- 用它们的替换替换所有出现的搜索字符串。
所以让我们倒计时,看看我们如何做到这一点:)
#!/usr/bin/perl
use strict; use warnings;
3.搜索和替换
我们将定义一个 sub 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
已经替换的字符串的一部分,但如果这是绝对必要的,可以解决这个问题。
2.遍历文件树
我们将定义一个名为anakinFileWalker
. 它以文件名或目录名和searchAndReplace
sub 作为参数。如果 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);
}
}
当然,如果你有循环符号链接,这个 sub 就会爆炸。
1. 设置%replacements
有一个不错的模块Text::CSV
可以帮助您满足所有需求。只要确保%replacements
满足上面的定义,但这并不难。
开始一切
准备好后%replacements
,我们就做
anakinFileWalker($topDirectory, \&searchAndReplace);
它应该可以工作。如果没有,这应该让您了解如何解决此类问题。
于 2012-09-02T12:29:24.400 回答