• Publicidad

Modificar líneas en fichero

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

Re: Modificar líneas en fichero

Notapor explorer » 2017-12-05 14:42 @654

Pueden pasar unas cuantas cosas...

Algunas de las que me he encontrado a lo largo de mi vida:

* la última línea del csv no tiene caracteres de fin de línea, y el programa fallaba al leer esa línea.

* todo lo contrario: la última línea contenía demasiados caracteres de fin de línea, y algunos de ellos "se pegaban" al nombre del archivo, por lo que el programa creaba un archivo con caracteres invisibles, al final del nombre.

* la última línea contiene los mismos datos que la penúltima, por lo que siempre fallaba al procesar los registros dos veces.

Haz una cosa: edita el programa para que lea el archivo csv y genere los archivos, y nada más. Debes comprobar que el número de archivos creados es igual al número de registros del csv.

Fíjate en ese momento si el último archivo está presente, y si tiene permisos distintos a los demás.

Vuelve a arrancar el programa para que haga el procesado del renombrado, pero poniendo un if como el que te he puesto antes. Puedes escoger varios test:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. if (! -e $archivo_entrada) {
  2.         die "ERROR: el archivo $archivo_entrada no existe\n";
  3. }
  4. if (! -f $archivo_entrada) {
  5.         die "ERROR: el archivo $archivo_entrada no es un archivo normal\n";
  6. }
  7. if (! -r $archivo_entrada) {
  8.         die "ERROR: el archivo $archivo_entrada no se puede leer\n";
  9. }
  10. if (! -w $archivo_entrada) {
  11.         die "ERROR: el archivo $archivo_entrada no se puede modificar\n";
  12. }
  13. if (  -z $archivo_entrada) {
  14.         die "ERROR: el archivo $archivo_entrada está vacío\n";
  15. }
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

Tienes más información en tu ordenador en perldoc -f -X .

Dices que el último archivo no te deja renombrarlo ni borrarlo. ¿Lo puedes borrar desde la línea de comandos?

Una forma muy clara para saber qué está manejando el programa es colocando print() de las variables principales, pero enmarcando los valores de las variables. Por ejemplo:

print "Archivo de partida: [$archivo_entrada]\n";

Si, al ejecutar el programa, en pantalla salen cosas como

[/TRABAJO-CMP/Boligan/Proyectos/Programacion/Decodificador_OBS_Perl/Proyecto-OBS-DB/1987-05.xml]
[/TRABAJO-CMP/Boligan/Proyectos/Programacion/Decodificador_OBS_Perl/Proyecto-OBS-DB/1933-05.xml]
[/TRABAJO-CMP/Boligan/Proyectos/Programacion/Decodificador_OBS_Perl/Proyecto-OBS-DB/2013-01.xml]

Todo va bien, pero si ves algo como esto

[/TRABAJO-CMP/Boligan/Proyectos/Programacion/Decodificador_OBS_Perl/Proyecto-OBS-DB/1987-05.xml]
[/TRABAJO-CMP/Boligan/Proyectos/Programacion/Decodificador_OBS_Perl/Proyecto-OBS-DB/1933-05.xml]
[/TRABAJO-CMP/Boligan/Proyectos/Programacion/Decodificador_OBS_Perl/Proyecto-OBS-DB/2013-01.xml
]

Observa el último archivo: el corchete está fuera de sitio. Eso quiere decir que el nombre del archivo contiene caracteres extra.

Nos falta más información para saber qué está pasando de verdad. ¿Puedes publicar las últimas 5 líneas del archivo csv, aunque sea falseando los datos sensibles?
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

Publicidad

Re: Modificar líneas en fichero

Notapor boligan » 2017-12-08 12:18 @554

Hola.

Bueno, explorer, como te comenté anteriormente el error me lo da cuando trata de leer el xml que le corresponde a la última línea del csv.

Aquí te pongo todo el código completo. Si puedes tírale un vistazo y dime qué ves mal. Yo estoy comenzando con Perl y realmente no me doy cuenta dónde está el error. Gracias por tu paciencia.

#use strict;
#use warnings;
#######################################################
# Recupera los nombres de archivos y directorios dentro de una ruta
#######################################################
##---PARA CARGAR Y CREAR FILE---
$carpeta="D:/Proyecto-OBS-DB";
$file="$carpeta/PasoRealdeSanDiego-1970-2015-Trihorario-csv-2010.csv";
#####DEFINICIONES ARREGLOS#############################
@hora=("00","03","06","09","12","15","18","21");
@mes=("Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre");
@est_name=("Cabo de San Antonio","La Bajada","Santa Lucia","Isabel Rubio","San Juan y Martinez","Pinar del Rio","La Palma","Paso Real de San Diego");
@var_name=("Estacion","Ano","Mes","Dia","Hora","Nubosidad","CantNubesClCm","AlturaNubeClCm","TipoNubesCl","TipoNubesCm","TipoNubesCh","DireccionViento","FuerzaViento","Visibilidad","TiempoPresente","TiempoPasado1","TiempoPasado2","PresionEstacion","PresionMar","CaracteristicaCurva","TendenciaBarometrica","TemperaturaSeca","TemperaturaHumeda","TensionVaporAgua","HumedadRelativa","DeficitSaturacion","PuntoRocio","Precipitacion","TemperaturaSuelo","Rocio","TemperaturaMinima6Horas","TemperaturaMaxima6Horas","Insolacion","Evaporacion","DireccionCl","DireccionCm","DireccionCh","EstadoCieloTropicos","EstadoSuelo","Bruma","Neblina","Niebla","Llovizna","Lluvia","Chubasco","Tormenta","Tornado","Granizo","CambioTemperatura","TiempoCambioTemperatura","GeneroNubesDesarrolloVertical","DireccionNubesDesarrolloVertical","AnguloElevacionNubesDesarrolloVertical","NubosidadCapa1","GeneroNubesCapa1","AlturaNubesCapa1","NubosidadCapa2","GeneroNubesCapa2","AlturaNubesCapa2","NubosidadCapa3","GeneroNubesCapa3","AlturaNubesCapa3","NubosidadCapa4","GeneroNubesCapa4","AlturaNubesCapa4");
#######################################################
open (ENTRADA,"<$file") || die "ERROR: No abre fichero de entrada $carpeta\n";
##---MAIN PROGRAM---
FINAL: while($fichero=<ENTRADA>){ # lee una línea del archivo
next if $fichero =~ m{^[\#]};
next if $fichero =~ m{^Estacion};
# final obs
if ($fichero =~ m/^([7][8][3][1][0-7])/){
leer_csv();
print "$valores_temp[1]-$valores_temp[2]\n";
# si el fichero existe, escribo, sino lo creo
$salida="$carpeta/$anocsv-$mescsv.xml";
if (-e $salida) {
open (SALIDA,">>$salida") || die "ERROR: No abre fichero de salida $salida\n";
print "EXISTE-$salida\n";
compara_csv_xml();
}else{
open (SALIDA,">$salida") || die "ERROR: No abre fichero de salida $salida\n";
print SALIDA "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Pinar>\n";
print "NO EXISTE-$salida\n";
llena_datos();
}
}
}
principio_y_final();
close (ENTRADA);close (SALIDA);
##---MAIN PROGRAM---
sub llena_datos {
for $j(0..$#var_name){
push @valor,"$var_name[$j]=\"$valores_temp[$j]\"";
}
$head=(" <Data ");# inicio obs
$end=(" />\n");
$archivo_valores="$head@valor$end"; # obs completa
print SALIDA $archivo_valores;
return @valor;
}
sub leer_csv{
@valores_temp=();@valor=();
@valores_temp=split(/[,]|\n$/,$fichero);
$estacioncsv=$valores_temp[0];
$anocsv=$valores_temp[1];
$mescsv=$valores_temp[2];
$diacsv=$valores_temp[3];
$horacsv=$valores_temp[4];
return;
}
sub leer_xml{
@valores_temp_xml=();
@valores_temp_xml=split(/\s+/,$ficheroxml,8);
$estacionxml=substr($valores_temp_xml[2],10,5);
$anoxml=substr($valores_temp_xml[3],5,4);
$mesxml=substr($valores_temp_xml[4],5,2);
$diaxml=substr($valores_temp_xml[5],5,2);
$horaxml=substr($valores_temp_xml[6],6,1);
return;
}
sub compara_csv_xml {
my $entradaxml=$salida;
open (ENTRADAXML,"<$entradaxml") || die "ERROR: No abre fichero de entrada $entradaxml\n";
while($ficheroxml=<ENTRADAXML>){ # lee una línea del archivo
if ($ficheroxml =~ m/<Data/){
@valores_temp_xml=();#print "hola-compara-$ficheroxml";
@valores_temp_xml=split(/\s+/,$ficheroxml,8);
$estacionxml=substr($valores_temp_xml[2],10,5);
$anoxml=substr($valores_temp_xml[3],5,4);
$mesxml=substr($valores_temp_xml[4],5,2);
$diaxml=substr($valores_temp_xml[5],5,2);
$horaxml=substr($valores_temp_xml[6],6,1);
#print "comparo-$estacioncsv-$estacionxml\n";
if ($estacioncsv==$estacionxml&&$diacsv==$diaxml&&$horacsv==$horaxml){
next FINAL;
}
}
}
llena_datos();
return;
}
sub principio_y_final {
# foreach (glob("$carpeta/*.xml")){
# @file_full=();
# print "encabeza-$_\n";
# $file_entrada=$_;
# $file_salida="$_.old";
# rename $file_entrada, $file_salida;
# open (IN,"<$file_salida") || die "ERROR: No abre fichero de entrada $!\n";
# open (OUT, ">$file_entrada") || die "ERROR: No abre fichero de salida $!\n";
# while($file=<IN>){ # lee una línea del archivo
# if ($file!~ m/<\/Pinar\>/){
# push @file_full,$file;
#print $file;
# }
# }
#print "@file_full";
# print OUT @file_full;
# print OUT "</Pinar>\n";
# close IN;
# close OUT;
# unlink $file_salida;
# my $num_removed = unlink $file_salida;
# print "$num_removed-files were removed\n";
# }
# return ;
for my $archivo_entrada (glob("$carpeta/2222-01.xml")) {
#my $archivo_nuevo = "$archivo_entrada.new";
my $archivo_viejo = "$archivo_entrada";
print "encabeza-$archivo_entrada\n";
#print "encabeza-$archivo_nuevo\n";
#chdir $carpeta or die "ERROR: No puedo entrar en el $carpeta: $!\n";
#print rename $archivo_nuevo, $archivo_viejo; # nuevo => viejo
#rename $archivo_viejo, $archivo_nuevo or die "ERROR al renombrar: $!\n";
open (IN,"<$archivo_viejo") or die "ERROR: No abre archivo de entrada $archivo_viejo: $!\n";
print "PRUEBA-1\n";
open my $OUT, '>', $archivo_nuevo or die "ERROR: No abre archivo de salida $archivo_nuevo: $!\n";
# if (! -e $archivo_entrada) {
# die "ERROR: el archivo $archivo_entrada existe";
# }
#print <IN>;
@file_full = <IN>;
#while ($linea = <IN>) {
print "PRUEBA-2\n";# lee una línea del archivo
# if ( $linea =~ m{</Pinar>} ) { # si es la marca que buscamos
# print $OUT "nueva información\n"; # insertamos la nueva información
# }
#print $linea;
# print $OUT $linea; # copiamos la línea leída al archivo de salida
#}
print "@file_full\n";
#print $OUT "</Pinar>\n";
close (IN);
close $OUT;
#print "$archivo_viejo\n";
#unlink $archivo_entrada; # borro los ficheros .old
}
return;
}
Adjuntos
PasoRealdeSanDiego-1970-2015-Trihorario-csv-2010.csv
(1.97 KiB) 180 veces
boligan
Perlero nuevo
Perlero nuevo
 
Mensajes: 20
Registrado: 2017-06-14 11:28 @519

Re: Modificar líneas en fichero

Notapor boligan » 2017-12-08 19:12 @841

Bueno, siguiendo tu consejo puse todos los if y el error es este...

if ( -z $archivo_entrada) {
die "ERROR: el archivo $archivo_entrada está vacío\n";
}

Archivo de partida: [D:/Proyecto-OBS-DB/2222.xml]
ERROR: el archivo D:/Proyecto-OBS-DB/2222.xml está vacío

o sea, que el fichero ESTÁ VACÍO... NO ENTIENDO...
boligan
Perlero nuevo
Perlero nuevo
 
Mensajes: 20
Registrado: 2017-06-14 11:28 @519

Re: Modificar líneas en fichero

Notapor explorer » 2017-12-08 21:03 @919

Explicación corta: El problema es que intentas acceder a un archivo que todavía no se ha cerrado, por lo que su información aún sigue en memoria, en el búfer, y en el disco sigue apareciendo con tamaño cero.

Explicación normal: resulta que cuando llamas a principio_y_final() al final del bucle principal, el último archivo TODAVÍA está esperando a que se cierre (hacer un close SALIDA). Perl todavía no lo ha grabado en disco. No falla con el resto de archivos, porque cada open SALIDA cierra el anterior. Pero eso no pasa con el último. Si colocas la línea

close (ENTRADA);close (SALIDA);

delante de

principio_y_final();

ya verás que funciona mucho mejor.

Explicación más detallada: cuando abres un archivo y escribes en él, en realidad lo haces a un búfer o memoria temporal, que cuando se llena, el sistema lo vuelca a disco. Esto se hace para no tener que escribir un byte cada vez a disco, sino uno o varios bloques de bytes, casi siempre coincidentes con el tamaño del sector de disco, para hacer las escrituras más eficientes.

Cuando termina el programa, cierras el archivo o abres otro archivo con el mismo gestor (SALIDA), lo que quedara en el búfer se graba y se limpia, y ya aparece el archivo en el sistema de archivos con su tamaño definitivo.

La solución es sencilla: cerrar los archivos lo más rápidamente posible. El problema de tu código es que mezclas llamadas a subrutinas, con aperturas y cierres de archivos, y lo más grabe: saltas de dentro de una subrutina llamada desde dentro del while() principal, hacia la siguiente vuelta de ese bucle, con un next. Es algo... muy lioso. Y no está garantizado que funcione bien en todos los Perl.

Te he preparado una versión de tu programa que hace lo mismo. Verás que a las subrutinas le pasamos la información que necesitan, para que luego nos devuelvan un solo valor o hagan algo concreto.

Esta versión no está optimizada, pero es para que te sea sencillo entender cómo funciona. En el siguiente mensaje te envío una versión más corta y más rápida.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. #use strict;
  3. #use autodie;
  4. #use warnings;
  5.  
  6.  
  7. #######################################################
  8. # Recupera los nombres de archivos y directorios dentro de una ruta
  9. #######################################################
  10.  
  11. ## Localizaciones -----------------------------------------------------------
  12. my $CARPETA = 'Proyecto-OBS-DB';
  13. my $CSV     = "$CARPETA/PasoRealdeSanDiego-1970-2015-Trihorario-csv-2010.csv";
  14.  
  15. ## Constantes ---------------------------------------------------------------
  16. my @hora     = qw(00 03 06 09 12 15 18 21);
  17. my @mes      = qw(enero febrero marzo abril mayo junio julio agosto septiembre octubre noviembre diciembre);
  18. my @est_name = (
  19.                 "Cabo de San Antonio",
  20.                 "La Bajada",
  21.                 "Santa Lucia",
  22.                 "Isabel Rubio",
  23.                 "San Juan y Martinez",
  24.                 "Pinar del Rio",
  25.                 "La Palma",
  26.                 "Paso Real de San Diego",
  27.             );
  28. my @var_name = qw(
  29.                 Estacion
  30.                 Ano     Mes     Dia     Hora
  31.                 Nubosidad       CantNubesClCm   AlturaNubeClCm  TipoNubesCl     TipoNubesCm     TipoNubesCh
  32.                 DireccionViento FuerzaViento
  33.                 Visibilidad
  34.                 TiempoPresente  TiempoPasado1   TiempoPasado2
  35.                 PresionEstacion PresionMar      CaracteristicaCurva     TendenciaBarometrica
  36.                 TemperaturaSeca TemperaturaHumeda       TensionVaporAgua
  37.                 HumedadRelativa DeficitSaturacion       PuntoRocio
  38.                 Precipitacion   TemperaturaSuelo        Rocio
  39.                 TemperaturaMinima6Horas TemperaturaMaxima6Horas
  40.                 Insolacion      Evaporacion
  41.                 DireccionCl     DireccionCm     DireccionCh
  42.                 EstadoCieloTropicos     EstadoSuelo
  43.                 Bruma   Neblina Niebla  Llovizna        Lluvia  Chubasco        Tormenta        Tornado Granizo
  44.                 CambioTemperatura       TiempoCambioTemperatura
  45.                 GeneroNubesDesarrolloVertical   DireccionNubesDesarrolloVertical
  46.                 AnguloElevacionNubesDesarrolloVertical
  47.                 NubosidadCapa1  GeneroNubesCapa1        AlturaNubesCapa1
  48.                 NubosidadCapa2  GeneroNubesCapa2        AlturaNubesCapa2
  49.                 NubosidadCapa3  GeneroNubesCapa3        AlturaNubesCapa3
  50.                 NubosidadCapa4  GeneroNubesCapa4        AlturaNubesCapa4
  51.             );
  52.  
  53. ## Proceso principal --------------------------------------------------------
  54. open my $ENTRADA, '<', $CSV or die "ERROR: No lee archivo de entrada [$CSV]: $!\n";
  55.  
  56. while (my $registro = <$ENTRADA>) {                                     # lee una línea del archivo
  57.     next if $registro =~ m{^#};                                         # saltar si es un comentario
  58.     next if $registro =~ m{^Estacion};                                  # saltar si es cabecera
  59.     next if $registro !~ m{^7831[0-7]};                                 # saltar si no nos interesa
  60.     chomp $registro;                                                    # quitamos caracteres de fin de línea
  61.  
  62.     my @campos = split /,/, $registro;                                  # partimos en campos
  63.  
  64.     print "Registro para $campos[1]-$campos[2]\n";
  65.  
  66.     # archivo XML que tenemos que actualizar
  67.     my $archivo_xml = "$CARPETA/$campos[1]-$campos[2].xml";
  68.  
  69.     if (!-e $archivo_xml) {
  70.         print "NO EXISTE $archivo_xml\n";
  71.  
  72.         # creamos un xml vacío
  73.         open my $SALIDA, '>', $archivo_xml or die "ERROR: No escribe archivo xml [$archivo_xml]: $!\n";
  74.         print   $SALIDA qq(<?xml version="1.0" encoding="utf-8"?>\n<Pinar>\n</Pinar>\n);
  75.         close   $SALIDA;
  76.     }
  77.  
  78.     # ver si tenemos información duplicada
  79.     my $esta = compara_csv_xml($archivo_xml, @campos);
  80.  
  81.     if (not $esta) {                            # si no está metida la información, la agregamos
  82.         actualiza_xml($archivo_xml, @campos);
  83.     }
  84. }
  85.  
  86. close $ENTRADA;
  87.  
  88. sub compara_csv_xml {
  89.     my $archivo_xml = shift;                            # primer argumento. Lo quitamos de @_
  90.     my @campos      = @_;                               # resto de argumentos
  91.  
  92.     my $esta = 0;                                       # Indicador de información presente
  93.  
  94.     open my $XML, '<', $archivo_xml or die "ERROR: No abre archivo xml [$archivo_xml]: $!\n";
  95.     while (<$XML>) {
  96.         next if not m{<Data (.+?)/>};           # saltamos si no es <Data>
  97.         my $xml_datos = $1;                     # Si lo es, capturamos su información con los paréntesis anteriores
  98.  
  99.         my $coincidencias = 0;                  # contaremos cuántas coincidencias hay con lo que buscamos
  100.  
  101.         for my $i (0,3,4) {                                     # en Estación, día y hora
  102.             my $var = $var_name[$i];                            # nombre de la variable
  103.             my($valor)  =  $xml_datos =~ /$var="(.+?)"/;        # buscamos esa $var en $xml_datos, y nos quedamos con el valor
  104.             last if $valor ne $campos[$i];                      # si son diferentes, no hace falta seguir mirando
  105.             $coincidencias++;                                   # sumamos una coincidencia más
  106.         }
  107.  
  108.         if ($coincidencias == 3) {
  109.             $esta = 1;                                          # sí tenemos información para esa estación/día/hora
  110.             last;                                               # no hace falta seguir mirando el resto del $XML
  111.         }
  112.     }
  113.  
  114.     close $XML;
  115.  
  116.     return $esta;
  117. }
  118.  
  119. sub actualiza_xml {
  120.     my $archivo_xml = shift;                            # primer argumento. Lo quitamos de @_
  121.     my @campos      = @_;                               # resto de argumentos
  122.  
  123.     # Primero leemos todo el archivo xml
  124.     open my $XML, '<', $archivo_xml or die "ERROR: No abre archivo xml [$archivo_xml]: $!\n";
  125.     my $xml = join '', <$XML>;          # leemos todas las líneas, en una sola variable $xml
  126.     close $XML;
  127.  
  128.     # Preparamos la información a agregar
  129.     my @valores;
  130.     for my $i (0 .. $#var_name){
  131.         push @valores, qq($var_name[$i]="$campos[$i]");
  132.     }
  133.     my $nueva = "  <Data @valores />\n";
  134.  
  135.     # Modificamos el $xml leído con la nueva información
  136.     # usamos la marca final de </Pinar> para agregarla al final
  137.     $xml =~ s{</Pinar>}{$nueva</Pinar>};
  138.  
  139.     # Guardamos el resultado
  140.     open my $SALIDA, '>', $archivo_xml or die "ERROR: No escribe a archivo xml [$archivo_xml]: $!\n";
  141.     print   $SALIDA $xml;
  142.     close   $SALIDA;
  143. }
Coloreado en 0.006 segundos, usando GeSHi 1.0.8.4
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: Modificar líneas en fichero

Notapor explorer » 2017-12-08 21:30 @937

Esta otra versión hace lo mismo, pero le he quitado las variables que no se usan, y he reducido la apertura de los archivos al mínimo.

El truco es leerse el archivo XML en memoria, trabajar con él, y luego guardar el xml ya modificado.

Con la ayuda del módulo autodie, no es necesario poner los "or die " cada vez que abrimos, cerramos o imprimimos a un archivo.


Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use strict;
  3. use autodie;
  4. use warnings;
  5.  
  6.  
  7. #######################################################
  8. # Recupera los nombres de archivos y directorios dentro de una ruta
  9. #######################################################
  10.  
  11. ## Localizaciones -----------------------------------------------------------
  12. my $CARPETA = 'Proyecto-OBS-DB';
  13. my $CSV     = "$CARPETA/PasoRealdeSanDiego-1970-2015-Trihorario-csv-2010.csv";
  14.  
  15. ## Constantes ---------------------------------------------------------------
  16. my @var_name = qw(
  17.                 Estacion
  18.                 Ano     Mes     Dia     Hora
  19.                 Nubosidad       CantNubesClCm   AlturaNubeClCm  TipoNubesCl     TipoNubesCm     TipoNubesCh
  20.                 DireccionViento FuerzaViento
  21.                 Visibilidad
  22.                 TiempoPresente  TiempoPasado1   TiempoPasado2
  23.                 PresionEstacion PresionMar      CaracteristicaCurva     TendenciaBarometrica
  24.                 TemperaturaSeca TemperaturaHumeda       TensionVaporAgua
  25.                 HumedadRelativa DeficitSaturacion       PuntoRocio
  26.                 Precipitacion   TemperaturaSuelo        Rocio
  27.                 TemperaturaMinima6Horas TemperaturaMaxima6Horas
  28.                 Insolacion      Evaporacion
  29.                 DireccionCl     DireccionCm     DireccionCh
  30.                 EstadoCieloTropicos     EstadoSuelo
  31.                 Bruma   Neblina Niebla  Llovizna        Lluvia  Chubasco        Tormenta        Tornado Granizo
  32.                 CambioTemperatura       TiempoCambioTemperatura
  33.                 GeneroNubesDesarrolloVertical   DireccionNubesDesarrolloVertical
  34.                 AnguloElevacionNubesDesarrolloVertical
  35.                 NubosidadCapa1  GeneroNubesCapa1        AlturaNubesCapa1
  36.                 NubosidadCapa2  GeneroNubesCapa2        AlturaNubesCapa2
  37.                 NubosidadCapa3  GeneroNubesCapa3        AlturaNubesCapa3
  38.                 NubosidadCapa4  GeneroNubesCapa4        AlturaNubesCapa4
  39.             );
  40.  
  41. ## Proceso principal --------------------------------------------------------
  42. open my $ENTRADA, '<', $CSV;
  43.  
  44. while (my $registro = <$ENTRADA>) {                                     # lee una línea del archivo
  45.     next if $registro !~ m{^7831[0-7]};                                 # saltar si no nos interesa
  46.     chomp $registro;                                                    # quitamos caracteres de fin de línea
  47.  
  48.     my @campos = split /,/, $registro;                                  # partimos en campos
  49.  
  50.     print "Registro para $campos[1]-$campos[2]\n";
  51.  
  52.     # archivo XML que tenemos que actualizar
  53.     my $archivo_xml = "$CARPETA/$campos[1]-$campos[2].xml";
  54.     my $xml;                                                            # contenido del xml
  55.  
  56.     if (!-e $archivo_xml) {
  57.         print "NO EXISTE $archivo_xml\n";
  58.  
  59.         # creamos un xml vacío
  60.         $xml = qq(<?xml version="1.0" encoding="utf-8"?>\n<Pinar>\n</Pinar>\n);
  61.     }
  62.     else {                                                              # lo leemos
  63.         local $/;
  64.         open my $XML, '<', $archivo_xml;
  65.         $xml = <$XML>;
  66.         close   $XML;
  67.     }
  68.  
  69.     # ver si tenemos información duplicada
  70.     if (not informacion_duplicada($xml, @campos[0..4])) {
  71.  
  72.         actualiza_xml($archivo_xml, $xml, @campos);
  73.     }
  74. }
  75.  
  76. close $ENTRADA;
  77.  
  78. sub informacion_duplicada {
  79.     my $xml    = shift;                                 # primer argumento. Lo quitamos de @_
  80.     my @campos = @_;                                    # resto de argumentos
  81.  
  82.     while ($xml =~ m{<Data (.+?)/>}g) {                 # buscamos todos los <Data>
  83.         my $xml_datos = $1;                             # capturamos su información con los paréntesis anteriores
  84.  
  85.         my $coincidencias = 0;                          # contaremos cuántas coincidencias hay con lo que buscamos
  86.  
  87.         for my $i (0,3,4) {                                     # en Estación, día y hora
  88.             my $var = $var_name[$i];                            # nombre de la variable
  89.             my($valor)  =  $xml_datos =~ /$var="(.+?)"/;        # buscamos esa $var en $xml_datos, y nos quedamos con el valor
  90.             last if $valor ne $campos[$i];                      # si son diferentes, no hace falta seguir mirando
  91.             $coincidencias++;                                   # sumamos una coincidencia más
  92.         }
  93.  
  94.         if ($coincidencias == 3) {
  95.             # sí tenemos información para esa estación/día/hora
  96.             # no hace falta seguir mirando el resto del $XML
  97.             return 1;
  98.         }
  99.     }
  100.  
  101.     return 0;
  102. }
  103.  
  104. sub actualiza_xml {
  105.     my $archivo_xml = shift;                            # primer argumento, el nombre del archivo
  106.     my $xml         = shift;                            # segundo argumento, el propio código xml
  107.     my @campos      = @_;                               # datos a agregar
  108.  
  109.     # Preparamos la información a agregar
  110.     my @valores;
  111.     for my $i (0 .. $#var_name){
  112.         push @valores, qq($var_name[$i]="$campos[$i]");
  113.     }
  114.     my $nueva = "  <Data @valores />\n";
  115.  
  116.     # Modificamos el $xml con la nueva información
  117.     # usamos la marca final de </Pinar> para agregarla al final
  118.     $xml =~ s{</Pinar>}{$nueva</Pinar>};
  119.  
  120.     # Guardamos el resultado
  121.     open my $SALIDA, '>', $archivo_xml or die "ERROR: No escribe a archivo xml [$archivo_xml]: $!\n";
  122.     print   $SALIDA $xml;
  123.     close   $SALIDA;
  124. }
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
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: Modificar líneas en fichero

Notapor boligan » 2017-12-12 12:42 @571

Hola, explorer.

Ya probé tu código y funciona a las mil maravillas. Ya le hice los cambios que yo necesitaba para mí, así que está funcionando bien. Muchísimas gracias.

Ahora, si me puedes sacar de esta duda...

Quiero desglosar la ruta de mis ficheros y obtener dónde están guardados las carpetas. Por ejemplo:

ruta: L:\2016\MARZO\01\

Esto sería año, mes y día.

Para esto le aplico el patrón:

$file=~/(\d{4})\/([A-Za-z]+)\/(\d{1,2})/;

y saco $1,$2,$3 que son año, mes y día, pero no me funciona. ¿Alguna idea?
boligan
Perlero nuevo
Perlero nuevo
 
Mensajes: 20
Registrado: 2017-06-14 11:28 @519

Re: Modificar líneas en fichero

Notapor explorer » 2017-12-12 14:18 @638

El problema está en las barras diagonales inversas. En tu ruta aparecen como '\', pero en el patrón consideras que son '/'.

Entonces, lo correcto sería
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$file =~ /(\d{4})\\([A-Za-z]+)\\(\d{1,2})/;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


De todas maneras, hay que recordar que los Windows modernos reconocen la barra diagonal normal, con lo que es más fácil trabajar.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.14;
  3.  
  4. my $ruta = 'L:/2016/MARZO/01/';
  5.  
  6. $ruta =~ m{(\d{4})/(\w+)/(\d{1,2})};
  7.  
  8. say "[$1][$2][$3]";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
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: Modificar líneas en fichero

Notapor boligan » 2017-12-12 15:43 @696

Perfecto, hermano, muchas gracias, ya tengo el script a punto, ya leo todos los ficheros y los guardo en base de datos xml. Muchas gracias, estoy en deuda contigo...
boligan
Perlero nuevo
Perlero nuevo
 
Mensajes: 20
Registrado: 2017-06-14 11:28 @519

Re: Modificar líneas en fichero

Notapor boligan » 2017-12-13 11:05 @503

Hola, explorer. Bueno, te sigo molestando. El script anterior deseo llamarlo desde un botón en una web, o sea, que el usuario al dar clic ejecute el script que me procesará los datos y los guardará en el xml que luego leeré con JavaScript en esa misma página.

Bueno, he buscado y todas las referencias que encuentro son para mostrar fotos, hacer formularios, etc., pero para ejecutar script perl no encuentro nada. ¿Alguna ayuda?
boligan
Perlero nuevo
Perlero nuevo
 
Mensajes: 20
Registrado: 2017-06-14 11:28 @519

Re: Modificar líneas en fichero

Notapor explorer » 2017-12-13 14:42 @654

Tienes que meter el botón en un formulario, y éste debe llamar al script, como si fuera un proceso cgi.

En esta web, en la sección CGI de los tutoriales, los que están al final, puedes aprender las bases de lo que es un CGI.

Luego, en el subforo Web hay muchos hilos que hablan de este tipo de llamadas.
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

Anterior

Volver a Básico

¿Quién está conectado?

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

cron