如果你打算用Perl打扰,何不干脆全力以赴,写(短)的Perl程序来做到这一点为你?
这样,你不会在shell和你的程序之间传递它,而你拥有更通用的东西,并且可以在多个操作系统上运行。
#!/usr/bin/env perl <-- Not needed for Windows, but tradition rules
use strict;
use warnings;
use feature qw(say);
use autodie; # Turns file operations into exception based programming
use File::Find; # Your friend
use File::Copy; # For the "move" command
# You could use Getopt::Long, but let's go with this for now:
# Usage = mungestrings.pl <from> <to> [<dir>]
# Default dir is current
#
my $from_string = shift;
my $to_string = shift;
my $directory = shift;
$from_string = quotemeta $from_string; # If you don't want to use regular expressions
$directory = "." if not defined $directory;
#
# Find the files you want to operate on
#
my @files;
find(
sub {
return unless -f; # Files only
return unless /\.txt$/ # Name must end in ".txt"
push @files, $File::Find::name;
},
$directory
);
#
# Now let's go through those files and replace the contents
#
for my $file (@files) {
open my $input_fh, "<", $file;
open my $output_fh, ">" "$file.tmp";
for my $line (<$input_fh>) {
$line =~ s/$from_string/$to_string/g;
print ${output_fh} $line;
}
#
# Contents been replaced move temp file over original
#
close $input_fh;
close $output_fh;
move "$file.tmp", $file;
}
我用File::Find
收集所有,我想在我的@files
数组来修改文件。我可以把整个事情的find
子程序内:
find(\&wanted, $directory);
sub wanted {
return unless -f;
return unless /\.txt/;
#
# Here: open the file for reading, open output and move the lines over
#
...
}
整个程序是在wanted
子程序这种方式。它更高效,因为我现在正在替换,因为我正在查找这些文件。无需先通过,找到文件,然后进行更换。然而,它让我觉得糟糕的设计。
您还可以发出声音的整个文件到一个数组,而无需通过其循环的第一:
open my $input_fh, "<", $file;
@input_file = <$input_fh>;
现在,你可以使用grep
进行检查,看是否有任何需要更换:
if (grep { $from_string } @input_file) {
# Open an output file, and do the loop to replace the text
}
else {
# String not here. Just close up the input file
# and don't bother with writing a new one and moving it over
}
这样更有效率(不需要做替换,除非该文件包含您正在查找的字符串)。但是,它占用了内存(整个文件一定在内存中),不要让这一行欺骗你。整个文件仍然一次一行地读入该数组中,就像您执行了整个循环一样。
File::Find
和File::Copy
是标准的Perl模块,所以所有的Perl安装都有它们。
关于独立于平台的解决方案...我昨天写了一段代码[File :: Find'](http://stackoverflow.com/a/24634420/2157640)。你可以用它来了解它的外观。 – Palec 2014-07-09 10:29:13