• Publicidad

Imprimir resultado con modificaciones

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

Imprimir resultado con modificaciones

Notapor sisifo80 » 2014-09-23 03:29 @187

Hola.

Estoy intentando hacer un script que realice ciertas modificaciones en varios XML. Se trata de eliminar ciertas etiquetas que aparecen dentro de la etiqueta <text>. Pero solo necesito eliminarlas cuando aparecen dentro de la etiqueta <text>. He intentado lo siguiente:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. opendir IN, 'input';
  2. my @in = grep {/^[^.]/} readdir IN;
  3. closedir IN;
  4.  
  5. for my $in (@in) {
  6.     open IN,  '<', "input/$in"  || next;
  7.     open OUT, '>', "output/$in" || die "can't open file output/$in";
  8.     $/ = undef;
  9.  
  10.     $file = <IN>;
  11.  
  12.     while ( $file =~ /<text id.*?>(.*?)<\/text>/gsmi ) {
  13.  
  14.         $text = $1;
  15.  
  16.         $text =~ s/<name>//g;
  17.         $text =~ s/<\/name>//g;
  18.         $text =~ s/<placeName>//g;
  19.         $text =~ s/<\/placeName>//g;
  20.         $text =~ s/<note n="contraction">(.*?)<\/note>/$1/g;
  21.  
  22.     }
  23.     print OUT $file;
  24.  
  25.     close OUT;
  26.     close IN;
  27. }
  28.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Mi problema es que el resultado que obtengo es el mismo que tenía en el archivo input, es decir, no se aplican las modificaciones que quiero. Si cambio la línea final de "print" por "print OUT $text" sí que se aplican las modificaciones, pero no obtengo todo el archivo input sino sólo la parte de <text>. Resumiendo:

a) puedo imprimir todo el input intacto
b) puedo imprimir la parte de <text> con las modificaciones

¿Cómo puedo imprimir todo el input con las modificaciones?

¡Gracias!
sisifo80
Perlero nuevo
Perlero nuevo
 
Mensajes: 32
Registrado: 2013-11-20 07:30 @354

Publicidad

Re: Imprimir resultado con modificaciones

Notapor explorer » 2014-09-23 04:47 @241

El asunto no es tan sencillo...

Estás extrayendo un contenido, para guardarlo en $text, y luego haces modificaciones en esa variable... pero luego no guardas las modificaciones en $file.

Fíjate en la solución siguiente:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use autodie;
  3.  
  4. open IN,  '<', "entrada.txt";
  5. open OUT, '>', "salida.txt";
  6. $/ = undef;
  7.  
  8. my $file = <IN>;
  9.  
  10. while ( $file =~ /<text id.*?>(.*?)<\/text>/gsmi ) {
  11.  
  12.     my $text = $1;
  13.     my $text_inicio = $-[1];
  14.     my $text_final  = $+[1];
  15.  
  16.     $text =~ s/<name>//g;
  17.     $text =~ s/<\/name>//g;
  18.     $text =~ s/<placeName>//g;
  19.     $text =~ s/<\/placeName>//g;
  20.     $text =~ s/<note n="contraction">(.*?)<\/note>/$1/g;
  21.  
  22.     substr($file, $text_inicio, $text_final - $text_inicio) = $text;
  23.     pos($file) = $text_inicio + length $text;
  24.  
  25. }
  26. print OUT $file;
  27.  
  28. close OUT;
  29. close IN;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Además de sacar $text, definimos dos variables más, en las que guardamos las posiciones iniciales y finales de esa captura.

Luego hacemos las modificaciones.

Y finalmente, con la ayuda de substr() "metemos" el nuevo $text dentro de $file, ajustando el tamaño (la longitud de lo extraído se ajusta al nuevo contenido).

Luego, con pos(), ajustamos la posición que usa el motor de expresiones regulares, para que comience la siguiente búsqueda justo donde hemos terminado el nuevo $text. Esto hay que hacerlo porque, al cambiar la longitud total de $file, si iniciáramos la siguiente vuelta de búsqueda, podríamos estar haciéndolo pasado el comienzo de un <text>, así que no lo detectaríamos. Por eso, colocamos el puntero justo donde hemos terminado (mejor dicho: colocamos el puntero justo delante del último </text>, pero no importa, porque el patrón buscará el siguiente <text>).
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: Imprimir resultado con modificaciones

Notapor sisifo80 » 2014-09-23 04:54 @245

Ok. Ya entiendo por qué no era capaz de imprimir como yo quería. Efectivamente, la cosa era menos sencilla de lo que yo creía. Había que jugar con la posición inicial y final de mi captura. Tu explicación es muy clara. ¡Gracias, explorer!
sisifo80
Perlero nuevo
Perlero nuevo
 
Mensajes: 32
Registrado: 2013-11-20 07:30 @354


Volver a Básico

¿Quién está conectado?

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