使用Perl在目录中的所有文件中递归替换多个字符串

时间:2012-09-02 11:26:26

标签: regex perl

我是perl的新手。看到了许多样本,但在编写解决方案时遇到了问题 我有一个字符串列表,每个字符串应该用不同的字符串a-> a2,b-> b34等替换。替换列表在某些csv文件中。需要递归地对目录中的所有文件执行此替换。 可能是任何其他语言,只是认为perl将是最快的

1 个答案:

答案 0 :(得分:4)

您的问题可以分为三个步骤:

  1. 从CSV文件中获取搜索和替换字符串
  2. 获取给定目录中所有文本文件的列表。子目录和
  3. 用替换替换搜索字符串的所有出现。
  4. 让我们做一个倒计时,看看我们如何做到这一点:)

    #!/usr/bin/perl
    use strict; use warnings;
    

    3。搜索和替换

    我们将定义一个子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子作为参数。如果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);
      }
    }
    

    当然,如果你有循环符号链接,这个子组就会爆炸。

    1。设置%replacements

    有一个很好的模块Text::CSV可以帮助您满足您的所有需求。只需确保%replacements符合上述定义,但这并不难。

    全部开始

    %replacements准备好后,我们就这样做了

    anakinFileWalker($topDirectory, \&searchAndReplace);
    

    应该工作。如果没有,这应该让你知道如何解决这个问题。