• Publicidad

Qué es el modo aspiradora

Así que programas sin strict y las expresiones regulares son otro modo de hablar. Aquí encontrarás respuestas de nivel avanzado, no recomendable para los débiles de corazón.

Qué es el modo aspiradora

Notapor danimera » 2014-08-11 14:26 @643

Hola, explorer. Por ahí saqué algo que tu usaste:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     open my $FILE, '<', $new_name."/".$file;
  2.     {
  3.         local $/;                              # activar modo aspiradora
  4.         $data_file = <$FILE>;                
  5.     }
  6.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Sé que lo hizo mágicamente, pero no sé qué es lo que pasa. Si no tengo ese modo aspiradora solo me queda la primera línea del manejador en $data_file, pero si lo pongo entonces en la variable $data_file tengo todo el contenido del fichero... :?
100% Telch - Perl Web Programming
Cali PerlMongers: http://cali.pm.org
Avatar de Usuario
danimera
Perlero frecuente
Perlero frecuente
 
Mensajes: 871
Registrado: 2005-06-23 19:02 @834
Ubicación: Colombia

Publicidad

Re: Qué es el modo aspiradora

Notapor explorer » 2014-08-11 16:15 @719

La variable especial $/ indica cuál es el delimitador de registros en los archivos de entrada (dice qué carácter o caracteres separan a unos registros de otros).

Lo interesante es ver lo que sucede con diversas combinaciones de valores para $/.

Sacado de (perldoc perlvar, y en la Web (traducido al español)):

IO::Handle->input_record_separator( EXPR )
$INPUT_RECORD_SEPARATOR
$RS
$/


El separador de registros a la entrada; de forma predeterminada, los caracteres que forman la nueva línea. Esto influye en la idea que tiene Perl de lo que es una "línea". Funciona como la variable RS del awk, incluyendo el tratamiento de líneas en blanco como un terminador si se establece a la cadena nula (una línea en blanco no puede contener espacios en blanco o tabuladores). Puede ponerle una cadena con varios caracteres para que coincida con un terminador de múltiples caracteres, o un "undef" para leer todo hasta al final del archivo. Si se establece a "\n\n" significa algo ligeramente diferente que si se establece a "", si el archivo contiene líneas en blanco consecutivas. Si se establece a "" tratará a dos o más líneas consecutivas vacías como una sola línea en blanco. Si se establece a "\n\n" asumirá ciegamente que el siguiente carácter de entrada pertenece al párrafo siguiente, incluso si se trata de un carácter de nueva línea.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. local $/;           # activa el modo aspiradora
  2. local $_ = <FH>;    # obtendremos aquí todo el archivo
  3. s/\n[ \t]+/ /g;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Recuerde: el valor de $/ es una cadena, no una expresión regular. Por algo awk tenía que ser mejor. :-)

(lo que sigue es incluso más interesante: $/ permite leer archivos con registros de tamaño fijo).

Cuando usas local(), estás creando una versión local de la variable, con un nuevo valor. Si no se indica ningún valor, es "undef". Y eso activa el modo aspiradora. Al final de las llaves, se recupera el valor original de $/ antes de haber sido local()izada.

Espero que esto te sirve. Si necesitas más detalles, pregunta y te lo detallo línea a línea.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Qué es el modo aspiradora

Notapor danimera » 2014-08-12 08:26 @393

A ver si entendí...

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. local $/;           # activa el modo aspiradora ¿¿¿ PERO CÓMO RAYOS HACE PARA ACTIVARLO SI AÚN  no leo el gestor de archivo???
  2.                     # entonces ¿él se lo aplica automáticamente al último gestor de archivo ?
  3. local $_ = <FH>;    # ¿obtendremos aquí todo el archivo? Ahora sí tengo el archivo
  4. s/\n[ \t]+/ /g;     # Yo creo que esto sobraría, ¿no es así?
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Veo que esto es tanto para Windows como para Linux, es decir que interpreta los saltos de línea tales como CR-LF , CR, LF.
100% Telch - Perl Web Programming
Cali PerlMongers: http://cali.pm.org
Avatar de Usuario
danimera
Perlero frecuente
Perlero frecuente
 
Mensajes: 871
Registrado: 2005-06-23 19:02 @834
Ubicación: Colombia

Re: Qué es el modo aspiradora

Notapor explorer » 2014-08-12 14:47 @658

Lo primero de todo... debes entender por qué usamos local()... porque... en realidad, no haría falta en muchas situaciones.

Respondiendo primero a tus preguntas: sí: la modificación de la variable afecta a todos los archivos abiertos y los que se vayan a abrir. Todos. Hasta el final del programa, o hasta que se recupere el valor inicial de $/.

Para que quede más claro: cambiar el valor a $/ a 'undef' no "activa" ningún "modo aspiradora", sino que le estamos diciendo a Perl que en cuanto le demos la orden de que lea un archivo, como hemos indefinido el delimitador de registros, lo leerá todo de golpe. Este comportamiento es como si hubiéramos puesto en marcha una aspiradora, por lo que, de forma graciosa, en la documentación se llama a esto "activar el modo aspiradora". Pero realmente solo estamos dándole un determinado valor a $/ para que se comporte así.

Supongamos que estamos en una situación en la cual el archivo que vamos a leer no tiene registros de entrada (las líneas de un archivo de texto serían los registros de ese archivo, separados con delimitadores -los caracteres de final de línea-), y decidimos que queremos leer todo el archivo de golpe, a una variable escalar. Bien porque tenemos memoria física para eso, o por simple comodidad (a veces es más fácil procesar todo el archivo, entero).

Entonces, siguiendo la documentación, podemos escribir esto:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use autodie;
  2.  
  3. open my $ARCHIVO, '<', 'archivo.txt';
  4.  
  5. undef $/;               # estas dos líneas hacen lo mismo: poner 'undef' en $/
  6. $/ = undef;             # podemos elegir cualquiera de ellas
  7.  
  8. my $archivo = <$ARCHIVO>;       # leemos todo el archivo
  9.  
  10. close $ARCHIVO;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Y ya tenemos a todo $archivo leído. (La tercera línea del código tuyo, es solo un ejemplo de lo que se puede hacer con el archivo leído. En ese caso, aplicar una expresión regular, que hace la sustitución de un conjunto de espacios en uno solo -es decir: que convierte a un texto en una sola línea-).

Pero... hay un "pequeño" problema...

Si el programa no tiene que leer más archivos, no pasa nada. Pero si tiene que leer más, tenemos el problema de que venimos con el valor de $/ cambiado... y a lo mejor el siguiente archivo a leer no queremos "aspirarlo", sino leerlo como un archivo de texto normal.

Entonces... deberíamos darle a $/ el valor que tenía antes, ya que sabemos que era el valor normal de caracteres de fin de línea.

Pero... ¿cuál? Eso depende del sistema operativo.

Si estamos en Linux, podemos hacer un $/ = "\n" y ya está. Pero entonces... nuestro programa ya no es portátil (no se puede llevar de un sistema operativo a otro) sin que tengamos que reeditarlo y cambiar esa línea.

Más cómodo es hacer esto: al principio del programa podemos ver qué valor tiene $/. Perl sabe en qué sistema operativo está y entonces sabe cuál es el delimitador por defecto para los caracteres de fin de línea.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $valor_anterior_RS = $/;
  2.  
  3. # ... resto del programa
  4.  
  5. # antes de abrir un archivo de texto, hacemos
  6. $/ = $valor_anterior_RS;
  7.  
  8. # ya podemos abrir archivos normales
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Y ya está resuelto: ya tenemos una forma de regresar a $/ el valor original.

Pero estamos en Perl... siempre hay otra manera de hacerlo, más cómoda.

La clave está en las llaves ({}). Para Perl, representan un "contexto" de trabajo o entorno de trabajo de las variables.

Toda variable local (declarada con my()) dentro de un par de llaves es destruida al final de ese contexto, y no conocida fuera de él. Es una buena forma de usar la variable $i en varios sitios donde necesitemos variables tontas para hacer cosas simples.

Pero hay otra forma de crear variables locales... y es con local().

local() no crea nuevas variables, sino que guarda los valores de las variables actuales en una pila aparte, y les asigna nuevos valores para ese contexto. Una vez que termina el contexto, se recuperan los valores originales.

Se usa también para cuando queremos que variables locales sean visibles dentro de subrutinas que llamemos (también, dentro del contexto).

Entonces, podemos reescribir el programa así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use autodie;
  2.  
  3. open my $ARCHIVO, '<', 'archivo.txt';
  4. my $archivo;                            # aquí lo guardaremos
  5. {                                       # creamos un contexto
  6.         local $/ = undef;               # creamos una variable local
  7.                                         # el valor anterior de $/ es guardado
  8.                                         # el valor inicial de $/ será 'undef'
  9.  
  10.         $archivo = <$ARCHIVO>;          # leemos todo el archivo
  11. }                                       # cerramos el contexto, $/ (local) se destruye, y $/ (global) recupera su valor original
  12. close $ARCHIVO;
  13.  
  14. # aquí podemos abrir otro archivo, ya de forma normal, ya que $/ tiene el valor correcto
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Si no le damos a local() un valor inicial, toma 'undef', así que la línea anterior se puede reducir a
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.         local $/;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Más información sobre local() en tu propio ordenador en perldoc perlsub, y en la Web.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Qué es el modo aspiradora

Notapor danimera » 2014-08-12 15:32 @689

Ahora sí me queda todo más claro, pero la última pregunta para mí sería ya que no estoy seguro es:

Cuando activo el "modo aspiradora" en un contexto... al recibir el contenido del archivo en una variable, ¿los caracteres de salto de línea siguen existiendo o los elimina?

Me explico: ¿podría yo volver a como originalmente venía el fichero o ya todo me quedará como si fuera en una sola línea?

Obvio: lo voy a testar en mi Perl :D
100% Telch - Perl Web Programming
Cali PerlMongers: http://cali.pm.org
Avatar de Usuario
danimera
Perlero frecuente
Perlero frecuente
 
Mensajes: 871
Registrado: 2005-06-23 19:02 @834
Ubicación: Colombia

Re: Qué es el modo aspiradora

Notapor Pichuzard » 2014-08-31 14:36 @650

La respuesta lógica es que no los elimina ya que no lo estás haciendo explícitamente en ningún lado. Te dejo un código donde probé esto, verás que imprimirá el archivo con todo y saltos de línea. Espero te sirva. :D
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use warnings;
  2. use strict;
  3.  
  4. my $arch='texto.txt';
  5. open ARCH, $arch or die 'No se pudo abrir';
  6. my $contenido;
  7. {
  8.         local $/;
  9.         $contenido=<ARCH>;
  10. }
  11. print "$contenido";
  12. close ARCH;
  13.  
  14. exit;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Pichuzard
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2014-05-15 17:13 @759


Volver a Avanzado

¿Quién está conectado?

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