Если вы собираетесь беспокоиться о Perl, почему бы просто не сделать все возможное и написать (короткую) программу на Perl, чтобы сделать это для вас?
Таким образом, вы не будете выдавать ее междуоболочка и ваша программа, и у вас есть что-то более универсальное и может работать в нескольких операционных системах.
#!/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.