• Publicidad

Leer y escribir a otro archivo de arriba hacia abajo

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Leer y escribir a otro archivo de arriba hacia abajo

Notapor ricky_jr » 2009-08-12 21:58 @957

¿Qué hay, compañeros?

Bueno, estoy empezando en esto de Perl y pues tengo un pequeño problema: tengo un archivo .txt que contiene líneas de texto y otro en blanco; lo que el programa debe hacer es que el die() reciba los dos archivos uno de lectura y el otro de escritura y pasar las líneas al archivo de escritura pero de forma que la última que se lee sea la primera que se escriba. Espero que me puedan ayudar en la brevedad posible.

Gracias.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2.  
  3. die "No hay argumentos que leer?\n" unless $ARGV[0];
  4. die "Escribe?\n"                    unless $ARGV[0];
  5. while(<>) {
  6.     @linea = split;
  7.     $cambio{$_} = $linea;
  8.     push(@otro, $cambio);
  9.     # La verdad no sé mi intención era hacer un pop()
  10.     # y no sé cómo escribir en el archivo en blanco;
  11.     # según yo sería algo así PERO ME MANDA ERROR
  12.     open ABRIR, ">escr.txt";
  13. }
  14. foreach (keys %cambio){
  15.     print ABRIR "$_ $cambio{$_} \n";
  16. }
  17. close ABRIR;
  18.  
  19. # AUXILIO
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Última edición por explorer el 2009-08-13 02:33 @148, editado 1 vez en total
Razón: Ortografía, indentación del código
ricky_jr
Perlero nuevo
Perlero nuevo
 
Mensajes: 13
Registrado: 2009-08-12 21:07 @921

Publicidad

Re: Leer y escribir a otro archivo de arriba hacia abajo

Notapor explorer » 2009-08-13 02:46 @157

Bienvenido a los foros de Perl en Español, ricky_jr.

El problema parece sencillo, no:
* Abrir el fichero a leer
* Leer todas sus líneas
* Abrir el fichero a escribir
* Escribir en él todas las líneas pero en sentido inverso

En el código que muestras lo tienes casi todo, pero cambiado de sitio.

No te hace falta usar un hash, si no con un array lo puedes resolver. Puedes guardar en él las líneas leídas.

Y recuerda que existe una función llamada reverse() que hace lo que necesitas.

Inténtalo de nuevo y mándanos otra prueba.

Hay errores también entre los nombres de las variables. Te recomiendo el uso de 'use strict;' y 'use warnings;' para que te ayuden a programar.

Por ejemplo, por alguna extraña razón usas la función split() (¿por qué necesitas dividir la línea que lees?) y lo dejas en una variable llamada @linea, que nunca más vuelves a usar. Lo mismo pasa con $linea, que no sabemos de dónde viene. Haces push() a @otro, pero tampoco lo vuelves a usar. Y lo que metes con el push() es $cambio, que tampoco sabemos de dónde viene.

¿El segundo die() no debería comprobar el valor de $ARGV[1]?
Última edición por explorer el 2009-08-13 16:28 @728, editado 1 vez en total
Razón: Ortografía
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Leer y escribir a otro archivo de arriba hacia abajo

Notapor Leo_Gutierrez » 2009-08-13 13:10 @590

Con lo poco que he aprendido, he tratado de solucionar la duda, algo así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. die("No hay argumentos de archivos a leer.\n $!") unless($ARGV[0]);
  5. die("No hay argumentos de archivo a escribir.\n $!") unless($ARGV[1]);
  6. open(FILE, "<$ARGV[0]") or die("No se pudo abrir el archivo. $!\n");
  7. open(SALIDA, ">$ARGV[1]") or die("No se pudo crear el archivo a escribir.\n $!");
  8. my @codigo = <FILE>;
  9. print SALIDA reverse(@codigo);
  10. close(FILE);
  11. close(SALIDA);
  12. exit(0);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Pero al correr el script sin argumentos, me da esta salida:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
leo@lein:~/Escritorio/pl$ perl pl.pl
No hay argumentos de archivos a leer.
 Descriptor de archivo inválido at pl.pl line 4.
leo@lein:~/Escritorio/pl$
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

¿Qué significa lo de "Descriptor de archivo inválido?
Leo_Gutierrez
Perlero nuevo
Perlero nuevo
 
Mensajes: 91
Registrado: 2008-08-20 23:38 @026

Re: Leer y escribir a otro archivo de arriba hacia abajo

Notapor explorer » 2009-08-13 16:38 @735

Lo del mensaje de error quiere decir que se ha intentado abrir un fichero con un descriptor o handle que no existe para el sistema.

Voy a decir algo, pero no estoy seguro de que sea así.

En las líneas 4 y 5 estás comprobando si el usuario ha escrito algún argumento. Si no lo haces, el programa muere.

El problema está en que al morir, estás sacando el mensaje de error almacenado en la variable $!... pero resulta que NO se ha producido NINGÚN error en el programa... simplemente, el usuario no ha escrito un argumento, pero eso no es un fallo del sistema o del programa.

Entonces, sospecho que el valor que saca $! no tiene nada que ver con el programa. En mi ordenador no sale ningún mensaje de error.

Casi mejor lo pones así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. if (@ARGV != 2) {
  6.     die "Uso: $0 <fichero a leer> <fichero a escribir>\n";
  7. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Así, estás comprobando que son exactamente dos los ficheros a entregar. El $0 equivale al nombre del programa. Y no sacamos $! porque no ha ocurrido ningún error de entrada/salida.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Leer y escribir a otro archivo de arriba hacia abajo

Notapor ricky_jr » 2009-08-14 13:01 @584

Pues sí es como dice nuestro amigo explorer y desafortunadamente no puedo usar el otro código ya que aún no llego a ese tema y ya saben cómo son los maestros. Bueno, creo que ya estoy muy cerca y he generado el siguiente código. Desafortunadamente sigue sin hacer nada. Haber si me pueden explicar la lógica más o menos cómo debería ir a; y por cierto, creo que explorer es un CABRÓN como decimos en México: he visto que responde muchas dudas; creo que es muy bueno... GRACIAS.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl

 die "No hay argumentos que leer?\n" unless $ARGV[0];
   die "Escribe?\n" unless $ARGV[1];
 while(<>) {
    $_=pop($otro);
       push( @otro, $cambio );
       
   
open ESC, ">escribir.txt";
}
foreach (%cambio){
        print ESC "$cambio{$_} \n";

}
close ESC;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Última edición por explorer el 2009-08-14 13:14 @593, editado 1 vez en total
Razón: Ortografía, sintaxis
ricky_jr
Perlero nuevo
Perlero nuevo
 
Mensajes: 13
Registrado: 2009-08-12 21:07 @921

Re: Leer y escribir a otro archivo de arriba hacia abajo

Notapor explorer » 2009-08-14 13:49 @617

El problema se puede resolver de muchas formas, claro, pero la lógica básica a usar te la puse más arriba, y que RockoX ha reproducido muy bien.

En cuanto a tu programa, solo hay que seguir lo que hace:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl

die "No hay argumentos que leer?\n" unless $ARGV[0];    # muérete si no hay un primer argumento
die "Escribe?\n" unless $ARGV[1];                       # muérete si no hay un segundo argumento
while (<>) {                                            # Hacemos un bucle por la entrada estándar
                                                        # y guardamos cada línea en $_
    $_ = pop($otro);                                    # Sacamos el primer elemento del array referenciado
                                                        # por $otro y lo guardamos en $_ : ERROR DE COMPILACIÓN
    push( @otro, $cambio );                             # El valor almacenado en $cambio lo guardamos
                                                        # en el array @otro
    open ESC, ">escribir.txt";                          # Abrimos un fichero en modo escritura
}                                                       # Esto lo repetimos para todas las líneas de la entrada estándar
foreach (%cambio) {                                     # Para todos los valores y claves del hash %cambio
    print ESC "$cambio{$_} \n";                         # Escribimos en un fichero supuestamente abierto antes
                                                        # el valor correspondiente a $cambio{$_}
}                                                       # Repetimos
close ESC;                                              # Cerramos el fichero abierto
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Vamos... ¡¡¡un jaleo tremendo!!!

* ¿Dónde se han definido las variables $otro, %cambio y $cambio?
* La información que guardamos en @otro no se usa nunca
* Abres el fichero de salida dentro de un bucle de lectura; y eso lo repites por cada línea de entrada
* Lees la línea de entrada en $_ pero en la línea siguiente, ¡te olvidas de ella!
* Creo que no tienes muy claro cómo recorrer los valores de hash
* ¿Un hash he dicho? ¿Para qué usas un hash? ¿Y dónde has creado ese hash?
* Hay un problema también muy gordo: cuando pones '<>', Perl abre el primer fichero indicado en los argumentos, y lo va pasando línea a línea. Y DESPUÉS, abre el SEGUNDO fichero indicado y hace lo mismo.

Necesitas repasar los apuntes :)

Mira, un truco: si al principio del programa pones estas líneas:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use warnings;
use diagnostics;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

y, desde la línea de comandos, ejecutas
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
perl -c kk.pl kk1.txt kk2.txt
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Entonces Perl te chiva lo que él cree que está mal:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Type of arg 1 to pop must be array (not scalar dereference) at kk.pl line 11, near "$otro)"
kk.pl had compilation errors (#1)
    (F) This function requires the argument in that position to be of a
    certain type.  Arrays must be @NAME or @{EXPR}.  Hashes must be
    %NAME or %{EXPR}.  No implicit dereferencing is allowed--use the
    {EXPR} forms as an explicit dereference.  See perlref.

Uncaught exception from user code:
        Type of arg 1 to pop must be array (not scalar dereference) at kk.pl line 11, near "$otro)"
kk.pl had compilation errors.
 at kk.pl line 24
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Que quiere decir que: el primer argumento de pop debe ser un array (no un escalar desreferenciado), en la línea 11. Luego te lo reexplica con más detalle. Y luego se muere.

Si, además, pones como primera línea ejecutable del programa esta otra:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use strict;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Entonces Perl trabaja en modo estricto, y nos dará más información:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
explorer@next3:~/Documents/desarrollo> perl -c kk.pl kk1.txt kk2.txt
Global symbol "$otro" requires explicit package name at kk.pl line 11.
Type of arg 1 to pop must be array (not scalar dereference) at kk.pl line 11, near "$otro)"
Global symbol "@otro" requires explicit package name at kk.pl line 13.
Global symbol "$cambio" requires explicit package name at kk.pl line 13.
Global symbol "%cambio" requires explicit package name at kk.pl line 17.
Global symbol "%cambio" requires explicit package name at kk.pl line 18.
kk.pl had compilation errors (#1)
    (F) You've said "use strict vars", which indicates that all variables
    must either be lexically scoped (using "my"), declared beforehand using
    "our", or explicitly qualified to say which package the global variable
    is in (using "::").

Uncaught exception from user code:
        Global symbol "$otro" requires explicit package name at kk.pl line 11.
Type of arg 1 to pop must be array (not scalar dereference) at kk.pl line 11, near "$otro)"
Global symbol "@otro" requires explicit package name at kk.pl line 13.
Global symbol "$cambio" requires explicit package name at kk.pl line 13.
Global symbol "%cambio" requires explicit package name at kk.pl line 17.
Global symbol "%cambio" requires explicit package name at kk.pl line 18.
kk.pl had compilation errors.
 at kk.pl line 24
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Y salen todos los errores comentados antes, sobre todo, todas las variables que Perl se encuentra de sopetón.

Esas tres líneas de 'use' son imprescindibles para cualquier programador nuevo en Perl, pues el intérprete perl le ayudará mucho.

Si te es más fácil, puedes resolver el problema usando los bucles for() con tres parámetros, recorriendo los elementos almacenados en el array, pero en orden inverso.

RockoX ya te ha dado una solución, pero no podemos resolverte el tema porque tu profesor seguramente estará leyendo esto también, así que no te valdrá lo que te digamos de forma directa.

Lo principal, a la hora de programar, es tener claro el plan general, y resolverlo paso a paso. A veces es interesante, al principio, resolverlo con lápiz y papel.

En cuanto a lo de cabrón, aquí en España solemos decir "¡Pero qué cabrón (que) es...!" Eso sí, no significa lo mismo si lo dices enfadado o con admiración. :)

Lo bueno del Español es que tenemos un idioma muy rico, y cada país tiene sus variaciones, que lo hacen aún más rico -a pesar de algún pequeño cambio de significado de algunas palabras :) -.
Última edición por explorer el 2009-08-14 17:35 @774, editado 2 veces en total
Razón: mejor explicación en código
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Leer y escribir a otro archivo de arriba hacia abajo

Notapor Leo_Gutierrez » 2009-08-14 14:13 @634

Hola a todos.

explorer, ya que estás hablando sobre "use strict", una pregunta:

¿Cuándo es necesario y cuándo no usar dicho pragma?

Te lo pregunto porque en los pequeños scripts que he hecho, siempre se lo pongo.
Leo_Gutierrez
Perlero nuevo
Perlero nuevo
 
Mensajes: 91
Registrado: 2008-08-20 23:38 @026

Re: Leer y escribir a otro archivo de arriba hacia abajo

Notapor netsoul » 2009-08-14 14:23 @641

Me gustó en la parte donde dice: # muérete si no hay un primer argumento
With Perl
Imagination is more important than knowledge. Albert Einstein.
netsoul
Perlero nuevo
Perlero nuevo
 
Mensajes: 150
Registrado: 2008-05-04 01:11 @091

Re: Leer y escribir a otro archivo de arriba hacia abajo

Notapor explorer » 2009-08-14 14:39 @652

La recomendación más actual sobre 'strict' es: usarlo SIEMPRE, en TODAS las circunstancias. Y da igual que sea corto o largo el programa o tengas un nivel de nobel o experto en Perl.

Solo habría unas pequeñas excepciones, pero la básica es:
* que un programa haya pasado de la fase de desarrollo a producción y sabemos que está libre de errores
* y que ese programa no va a ser modificado (al menos a corto plazo)
* y que es vital ahorrar el tiempo añadido de proceso que este pragma añade al nuestro (muchas veces, es casi inapreciable ese tiempo extra).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Leer y escribir a otro archivo de arriba hacia abajo

Notapor Leo_Gutierrez » 2009-08-14 14:44 @656

Bueno, lo usaré siempre.

Gracias por la pronta respuesta.
Leo_Gutierrez
Perlero nuevo
Perlero nuevo
 
Mensajes: 91
Registrado: 2008-08-20 23:38 @026

Siguiente

Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 2 invitados

cron