我需要对不同目录(不递归)的文件的内容进行多次替换。
例如,对于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);
}
答案 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/%' {} \;