1

私はperlを初めて使用します。多くのサンプルを見ましたが、解決策の作成に問題がありました。各文字列を別の文字列a-> a2、b->b34などに置き換える必要がある文字列のリストがあります。置換のリストはいくつかのcsvファイルにあります。ディレクトリ内のすべてのファイルに対してこの置換を再帰的に実行する必要があります。perlが最速だと思った他の言語かもしれません

4

1 に答える 1

4

問題は次の3つのステップに分けることができます。

  1. CSVファイルから検索と置換の文字列を取得します。
  2. 特定のディレクトリ内のすべてのテキストファイルのリストを取得します。サブディレクトリ、および
  3. 検索文字列のすべての出現箇所をそれらの置換で置き換えます。

それでは、カウントダウンを実行して、それをどのように実行できるかを見てみましょう:)

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

3.検索して置換

subを定義しますsearchAndReplace。引数としてファイル名を取り、外部ハッシュにアクセスします。これをハッシュと呼びます%replacements。各キーは置換する文字列であり、値は置換です。これは、検索文字列ごとに1つの置換しかできないという制限を「課します」が、それは当然のように思われるはずです。さらに、各ファイルは適度に小さい(つまり、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);

そしてそれは動作するはずです。そうでなければ、これはあなたにそのような問題を解決する方法についての考えを与えるはずです。

于 2012-09-02T12:29:24.400 に答える