如何在多个目录中的每个文件的内容上执行多个替换?

时间:2011-10-12 12:18:00

标签: perl file-io substitution

我需要对不同目录(不递归)的文件的内容进行多次替换。

例如,对于dir / foo / bar 中的所有文件:

s/blue/red/;
s/green/yellow/;

对于dir / foobar / bar 中的所有文件:

s/orange/black/;

编写此脚本的最有效方法是什么?

我的替换脚本目前都是单行的,所以我对如何将它们完整地整合到一个完整的脚本中一无所知。


我已经在下面的非功能性测试脚本中添加了一个片段,如果它有用的话。

opendir(DIR, $dir) or die "Cannot open directory: $!\n";
my @files = readdir(DIR);
closedir(DIR);

foreach(@files) {
    my $filename = $_;   
    open(FILE, $filename);

    while (my $data = <FILE>) {
        # Substitution lines
        }
    close(FILE);
    }

3 个答案:

答案 0 :(得分:3)

您可以尝试使用perl one-liner来解决问题:

perl -i".bak" -n -e 's/blue/glue/g; print;' *

你可以使用很多-e,或者使用很多s ///。这也会备份当前文件。

希望这有帮助。

答案 1 :(得分:0)

我已更新代码以匹配您想要的内容,您将不得不使用模块 解析命令行args如Getopt :: Long;我不确定语法,但是你需要一些允许你在两端做字符串数组的东西;我确信有一种更好的方法来处理args,这样你就可以将它们作为关键的值映射来阅读。

#!/usr/bin/perl
# invoke with:
# script.pl <name part to match> <name part to replace> <directory to examine> <directory to examine...>
use Getopt::Long;
my %opts = ();

... read in match keys / values ...

my $dir = shift;
while(-d $dir){
    @files_in_dir = <$dir/*>;
    foreach my $file (@files_in_dir){
        my @lines = ();
        open(my $IN, '<', $dir/$file);
        while(<$IN>){
            foreach $i (1..#@$opt{match}){
                if(/@{$opt{match}}[$i]/){
                    s/@{$opt{match}}[$i]/@{$opt{replace}}[$i]/;
                }  
            }
            push @lines, $_;
        }
        close $IN;
        open(my $OUT, '>', $dir/$file);
        print $OUT "$_" foreach(@lines);
        close $OUT;
    }
    $dir = shift;
}

答案 2 :(得分:0)

目录遍历可能是一个很大的瓶颈,所以你应该尝试只做一次。

find . -type f -exec perl -i".bak" -pe '
  if($ARGV =~ m%^./foo/bar/%){s/blue/red/g;s/green/yellow/g;}
  s/orange/black/ if($ARGV =~ m%^./foobar/bar/%' {} \;