• Publicidad

Guardar variable y reemplazarla por otra

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

Guardar variable y reemplazarla por otra

Notapor lis » 2016-08-22 17:04 @753

Estimados perleros: Tengo un archivo con extensión .kml y lo que quiero es buscar una línea especifica (muy larga) que contiene un valor determinado. Este valor debe reemplazar esa línea. El código que tengo identifica los valores de cada línea pero no sé cómo reemplazarlos. Por ejemplo esta es la línea que busco (que se repite unas cuantas veces) dentro del archivo kml adjunto:

Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
  1. <description>
  2. <![CDATA[<table width="300" border="0" cellspacing="3" cellpadding="3"><tr><td colspan="2"><div align="left"><font size="+2"><b>CALPOST Results: Level 1</b></font><hr/></div></td></tr><tr><td height="119" colspan="2"><table width="100%" border="0" align="center" cellpadding="3" cellspacing="4"><tr bgcolor="#DCE8EE"><td width="50%"><div align="right"><b>Min Level</b></div></td><td width="50%">3</td></tr><tr bgcolor="#DCE8EE"><td width="50%"><div align="right"><b>Max Level</b></div></td><td width="50%">5</td></tr></table></td></tr><tr><td width="100%"><a href="http://www.weblakes.com" target="_blank"><img src="http://www.weblakes.com/images/Lakes_Logo_Google.gif" alt="logo" border="0" /></a></td><td width="200"><p align="right"><font size="3" color="#666666">CALPUFF View 5.0.1<br><a href="http://www.webLakes.com">www.webLakes.com</a><br>Lakes Environmental Software</font></td></tr></table>]]>
  3. </description>
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

y lo que quiero lograr es que quede así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
  1. <description>
  2. 3
  3. </description>
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Ese número tres viene después de "Min Level</b></div></td><td width="50%">3<".

Les muestro mi código que identifica esos valores y las líneas a reemplazar (que está comentada), pero no sé cómo guardarlas en variables y reemplazarlas, y dejar el resto del archivo igual.

Les agradezco muchísimo su tiempo y ayuda.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use diagnostics;
  4. use warnings;
  5.  
  6. open my $FILE, '<' , 'mp10p98contru.kml';
  7. my @archivo = <$FILE>;
  8. close $FILE;
  9.  
  10. for my $linea (@archivo) {
  11.     if ($linea =~ />(\d+.?\d*)</) {
  12.         print "$1\n";
  13.         # print "$linea" if $linea =~ /^(<!\[CDATA\[<table\s)|(\/table>\]\]>)$/;
  14.     }
  15. }
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Adjuntos
mp10p98contru.kml.zip
Archivo kml comprimido
(22.2 KiB) 98 veces
lis
Perlero nuevo
Perlero nuevo
 
Mensajes: 106
Registrado: 2008-05-27 21:43 @946

Publicidad

Re: Guardar variable y reemplazarla por otra

Notapor explorer » 2016-08-22 19:40 @861

Bueno, el problema es sencillo: una operación de sustitución (s///) de forma repetida por todo el documento (/g).
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2.  
  3. my $kml;
  4. {
  5.     local $/;                                   # activar el modo aspiradora
  6.     open my $FILE, '<', 'mp10p98contru.kml';
  7.     $kml = <$FILE>;                             # todo el archivo pasa a un solo escalar
  8.     close   $FILE;
  9. };
  10.  
  11. # buscamos el patrón, y si lo encontramos, lo reemplazamos por lo que queremos.
  12. $kml =~ s{<description>.+?Min Level</b></div></td><td width="50%">(.+?)</td>.+?</description>}
  13.          {<description>\n$1\n</description>}msg;
  14.  
  15. print $kml;
  16.  
  17. # aquí guardaríamos $kml a un archivo
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

De todas maneras, buscar en XML con exp. reg. es propenso a que no funcione en el futuro (si cambia el XML, fallará el programa). Es mejor usar técnicas de DOM, pero bueno, para una cosa rápida, puede valer.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14475
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Guardar variable y reemplazarla por otra

Notapor lis » 2016-09-24 08:43 @405

Hola, explorer. Muchas gracias por el código y lamento no haber respondido antes debido a que mi país estuvo de aniversario de fiestas patrias, y fueron unas "mini vacaciones" :D

Respecto del archivo .kml adjunto, tu código funciona impecablemente, pero este archivo contiene datos tanto en forma de polígonos (Polygon) como de líneas (LineString), y no sé por qué en este último formato se pierde un dato de información por lo cual necesito eliminarlo (en este archivo empieza de la línea 1571 y termina en la 2379) y lo hago de la siguiente manera:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. while(my $kml=<*.kml>){
  3.     my $k2 = qx{perl -i -0777 -p -e 's|(<Placemark>.*?<\/Placemark>)| $1 =~ /<LineString>/?"":$1|gse' $kml};
  4.     system $k2;
  5. }
  6.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


El tema es que si lo ejecuto así no me funciona, me da el siguiente error:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  1. Use of ?PATTERN? without explicit operator is deprecated at -e line 1.
  2. syntax error at -e line 1, near "{  =~"
  3. Search pattern not terminated or ternary operator parsed as search pattern at -e line 1.
  4.  
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Pero si lo ejecuto directamente en la consola funciona perfectamente:

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. perl -i -0777 -p -e 's|(<Placemark>.*?<\/Placemark>)| $1 =~ /<LineString>/?"":$1|gse' mp10ppcont.kml
  2.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


explorer, agradezco mucho tu ayuda.
lis
Perlero nuevo
Perlero nuevo
 
Mensajes: 106
Registrado: 2008-05-27 21:43 @946

Re: Guardar variable y reemplazarla por otra

Notapor explorer » 2016-09-24 10:05 @462

Hay varios problemas, y muy gordos.

El primero, es que estás usando el operador qx() para ejecutar un comando externo, y luego ejecutas system() con el resultado de la anterior ejecución.

Quiero decir que qx() YA ejecuta el comando que contiene. Y el resultado se lo pasas a system(), sin saber por qué necesitas ejecutar el resultado.

Otro problema es que las variables, dentro de qx() son interpoladas. Así que las apariciones de $1 son interpoladas. Y como en ese momento $1 no vale nada, lo que realmente ocurre es que desaparecen. Deberías escaparlas.

En resumen, que el código quedaría a algo así (no probado):
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. while (my $kml=<*.kml>){
  3.     system('perl', q(-i -0777 -p -e 's|(<Placemark>.*?<\/Placemark>)| $1 =~ /<LineString>/?"":$1|gse'), $kml);
  4. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Solo necesitamos ejecutar un comando cada vez, y no nos interesa la salida del resultado, así que sustituimos qx() por un system().

Dentro de él, no pasamos todo el comando en un único elemento o cadena de caracteres, porque eso provoca la ejecución de un shell, y por lo tanto, la expansión de las variables que el shell encuentre, algo que no queremos. Por eso, le pasamos a system() 3 argumentos. El primero es el nombre del ejecutable a arrancar, y el resto son los argumentos. De esta manera, no hay expansión de variables (más información en perldoc -f system).

Nota: el operador q() sirve para entrecomillar "simple" cuando existen comillas simples en el texto. Ver perldoc -f q.

Por otra parte... ¿Ejecutar perl dentro de perl? Casi mejor si ejecutas perl dentro de bash. O mejor aún si lo haces todo en un solo programa perl (hay un ejemplo en la explicación de '-i' en perldoc perlrun).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14475
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Guardar variable y reemplazarla por otra

Notapor lis » 2016-09-27 09:02 @418

Gracias, explorer, seguí tu consejo y lo hice a través de bash y este es el código:

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. #!/bin/bash
  2. #! -*-perl-*-
  3.  
  4. perl -i -0777 -p -e 's|<description>.+?Min Level</b></div></td><td width="50%">(.+?)</td>.+?</description>|<description>\n$1\n</description>|msg' *.kml
  5.  
  6. perl -i -0777 -p -e 's|(<Placemark>.*?<\/Placemark>)| $1 =~ /<LineString>/?"":$1|gse' *.kml
  7.  
  8. for f in *.kml;
  9. do
  10. s=${f%.*}.shp
  11. s2=${f%.*}2.shp
  12. ogr2ogr $s2 $f -nlt LineString -skipfailures ;
  13. ogr2ogr -sql "SELECT Name,cast(Descriptio as float) FROM ${f%.*}2" $s $s2;
  14. rm *2.*
  15. done
  16.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Mil gracias por tu orientación.
lis
Perlero nuevo
Perlero nuevo
 
Mensajes: 106
Registrado: 2008-05-27 21:43 @946


Volver a Básico

¿Quién está conectado?

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

cron