Si vas a molestar con Perl, ¿por qué no simplemente ir a por todas y escribir una (corta) programa de Perl para hacer esto ¿para ti?
De esta manera, no pasará entre el shell y su programa, y tendrá algo que es más universal y puede ejecutarse en múltiples sistemas operativos.
#!/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;
}
utilizo File::Find
para reunir todos los archivos que desea modificar en mi arsenal @files
. Podría haber puesto todo el asunto dentro de la subrutina 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
#
...
}
El conjunto del programa se encuentra en la wanted
subrutina de esta manera. Es más eficiente porque ahora estoy reemplazando ya que estoy buscando los archivos. No es necesario pasar primero, encontrar los archivos, luego hacer el reemplazo. Sin embargo, me parece un mal diseño.
También puede sorber todo su archivo en una matriz sin bucle a través de él al principio:
open my $input_fh, "<", $file;
@input_file = <$input_fh>;
Ahora, puede utilizar grep
comprobar para ver si hay algo que necesita ser reemplazado:
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
}
Esto es más eficiente (no es necesario reemplazar, a menos que ese archivo tenga la cadena que está buscando). Sin embargo, ocupa memoria (todo el archivo debe estar en la memoria al mismo tiempo), y no dejes que esa línea te engañe. El archivo completo aún se lee en esa matriz una línea a la vez como si hiciera un ciclo completo.
File::Find
y son módulos estándar de Perl, por lo que todas las instalaciones de Perl los tienen.
En cuanto a la solución independiente de la plataforma ... Escribí [un fragmento de código con 'File :: Find'] (http://stackoverflow.com/a/24634420/2157640) ayer. Puede usar eso para tener una idea de cómo podría ser. – Palec