2010-12-19 28 views
8

¿Hay alguna forma con las bibliotecas estándar de Perl para abrir un archivo y editarlo, sin tener que cerrarlo y luego abrirlo de nuevo? Todo lo que sé hacer es leer un archivo en una cadena, cerrar el archivo y luego sobrescribir el archivo con uno nuevo; o leer y luego anexar al final de un archivo.Abrir archivo para leer y escribir (no anexar) en perl

Actualmente funciona pero; Tengo que abrirlo y cerrarlo en dos ocasiones, en lugar de una vez:

#!/usr/bin/perl 
use warnings; use strict; 
use utf8; binmode(STDIN, ":utf8"); binmode(STDOUT, ":utf8"); 
use IO::File; use Cwd; my $owd = getcwd()."/"; # OriginalWorkingDirectory 
use Text::Tabs qw(expand unexpand); 
$Text::Tabs::tabstop = 4; #sets the number of spaces in a tab 

opendir (DIR, $owd) || die "$!"; 
my @files = grep {/(.*)\.(c|cpp|h|java)/} readdir DIR; 
foreach my $x (@files){ 
    my $str; 
    my $fh = new IO::File("+<".$owd.$x); 
    if (defined $fh){ 
     while (<$fh>){ $str .= $_; } 
     $str =~ s/(|\t)+\n/\n/mgos;#removes trailing spaces or tabs 
     $str = expand($str);#convert tabs to spaces 
     $str =~ s/\/\/(.*?)\n/\/\*$1\*\/\n/mgos;#make all comments multi-line. 
     #print $fh $str;#this just appends to the file 
     close $fh; 
    } 
    $fh = new IO::File(" >".$owd.$x); 
    if (defined $fh){ 
     print $fh $str; #this just appends to the file 
     undef $str; undef $fh; # automatically closes the file 
    } 
} 
+0

1k + vistas y solo 1 voto popular. . . – GlassGhost

+0

2 upvotes ahora: D – GLES

Respuesta

15

Ya abierto el archivo para lectura y escritura abriéndolo con el modo <+, simplemente no está haciendo nada útil con él - si desea reemplazar el contenido del archivo en lugar de escribir en la posición actual (el final del archivo), debe volver al principio, escribir lo que necesite y luego truncate para asegurarse de que no quede nada. si hiciste el archivo más corto.

Pero como lo que intenta hacer es filtrar un archivo en el lugar, ¿le sugiero que use la extensión de edición in situ de perl, en lugar de hacer todo el trabajo usted mismo?

#!perl 
use strict; 
use warnings; 
use Text::Tabs qw(expand unexpand); 
$Text::Tabs::tabstop = 4; 

my @files = glob("*.c *.h *.cpp *.java"); 

{ 
    local $^I = ""; # Enable in-place editing. 
    local @ARGV = @files; # Set files to operate on. 
    while (<>) { 
     s/(|\t)+$//g; # Remove trailing tabs and spaces 
     $_ = expand($_); # Expand tabs 
     s{//(.*)$}{/*$1*/}g; # Turn //comments into /*comments*/ 
     print; 
    } 
} 

Y ese es todo el código que necesita - perl maneja el resto. Configurar $^I variable es equivalente a usar -i commandline flag. Realicé varios cambios en el código a lo largo del proceso: use utf8 no hace nada para un programa sin literal UTF-8 en la fuente, binmode stdin ystdout no hacen nada para un programa que nunca usa stdin o stdout, guardar CWD no hace nada para un programa que nunca chdir s. No había ninguna razón para leer cada archivo al mismo tiempo, así que lo cambié a linewise e hice que las expresiones regulares fueran menos incómodas (y dicho sea de paso, el modificador de expresiones regulares /o es bueno para casi nada en estos días, excepto agregar errores difíciles de encontrar a tu código).

+1

+1 para '$^I' :-) – friedo

+0

@hobbs, El proceso está basado en línea. ¿Qué ocurre si quiero usar regexp que contenga nueva línea? – solotim

+1

@solotim depende de los detalles. Puede cambiar '$ /' a algo más apropiado que '" \ n "' - en particular, si establece '$ /' en 'undef', entonces perl leerá todo el contenido del archivo en una sola lectura, le permite modificarlos, y luego escribir de nuevo. La memoria es lo suficientemente grande como para que sea un enfoque razonable para muchos archivos. Pero si no es así, tendrás que hacer el trabajo por tu cuenta. – hobbs

Cuestiones relacionadas