Perl en Español

  1. Home
  2. Tutoriales
  3. Foro
  4. Artículos
  5. Donativos
  6. Publicidad
 

Comparar ficheros en base a un mismo campo clave

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Experto
Mensaje Lun Ene 21, 2008 5:55 am
chemaff
Perlero Nuevo
Perlero Nuevo
Registrado: 21 Ene 2008
Mensajes: 4
Comparar ficheros en base a un mismo campo clave Responder citando

Hola,
necesito ayuda sobre cómo comparar 2 ficheros. Ambos ficheros tienen un campo clave en común y necesito crear un fichero de salida con la diferencias entre ambos solo si no coincide este campo clave.

Si alguien me puede marcar unas líneas muy generales creo que yo podré acabar solo el programa.

No sé si aquí, en Experto, es el lugar adecuado.

Creo que no me sirve:

Perl:
use File::Compare;    if (compare("file1","file2") == 0) ...


Muchas Gracias
Mensaje Lun Ene 21, 2008 6:52 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4130
Ubicación: Valladolid, España
Responder citando

No nos has dicho el formato de esos ficheros. ¿Son de texto?
Tampoco como se organizan los datos y la clave. ¿Están separados/colocados de alguna manera?
Mensaje Mie Ene 23, 2008 4:03 am
chemaff
Perlero Nuevo
Perlero Nuevo
Registrado: 21 Ene 2008
Mensajes: 4
Comparar ficheros de texto .csv por un campo clave Responder citando

Hola,

Tienes razón me dejado algunos datos importantes.
Son dos ficheros de texto en formato .csv, delimitados por ";".
La clave es alfanumérica.

De momento he encontrado una solución aunque no sé si es la mejor; tal vez Perl permita una manera mejor y mas rápida de hacerlo.

La solución que estoy desarrollando (aún no lo he terminado) es hacer 2 bucles while anidados, en cada bucle recorro un fichero y en el while más adentro al llegar al final de fichero vuelvo a ponerlo al principio con un seek fichero,0,0.

Más o menos es esto:
Perl:
open (CL_UNO,"<CL_UNO.csv") ;
open (CL_DOS, "<CL_DOS.csv")  ;

open (CL_RESULTADO,">>CL_RESULTADO.csv")  ;

while($linUno = <CL_UNO>) {
   chop($linUno);       
   @alinUno=split(";",$linUno);
     
   while($linDos = <CL_DOS>) {
      chop($linDos);
          @alinDos=split(";",$linDos);

       if  if ( $alinUno[0]  != $alinDos[0] )   {   
       print CL_RESULTADO "$linUno \n" ;      }
   }
   seek CL_DOS, 0, 0    ## ir la principio del fichero
}


Gracias.
Mensaje Mie Ene 23, 2008 6:15 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4130
Ubicación: Valladolid, España
Responder citando

Es decir... si el primer fichero tiene, por ejemplo 12 claves distintas y el segundo fichero tiene otras 12 claves distintas y distintas también del primero, ¿debe generar 144 print?
Mensaje Mie Ene 23, 2008 6:03 pm
Jenda
Perlero Frecuente
Perlero Frecuente
Registrado: 29 Oct 2007
Mensajes: 106
Ubicación: Praga, Republica Checa
Responder citando

Creo que necesitamos algunos ejemplos de lo que quieres.

Si tienes un fichero con
Código:
1;blah
2;blah

y otro con
Código:
2;blah
1;blah

¿son diferentes? Y si tienes
Código:
1;blah
2;blah
3;blah

y en otro
Código:
1;blah
4;blah
2;blah
3;blah

¿quieres que el script imprima solo que hay una clave nueva o quieres que imprima tres veces que las líneas son diferentes? ¿O algo completamente diferente?

Jenda
Mensaje Jue Ene 24, 2008 4:12 am
chemaff
Perlero Nuevo
Perlero Nuevo
Registrado: 21 Ene 2008
Mensajes: 4
Comparar ficheros de texto .csv por un campo clave Responder citando

Siempre comparo el fichero UNO con el fichero DOS y me interesa guardar en un fichero nuevo de salida el registro/linea que tenemos en UNO y que no tenemos en fichero DOS.
Puede que mas adelante necesite hacerlo al revés (comparar fichero DOS con UNO) pero de momento no lo necesito.

Por ejemplo si el fichero UNO tiene
Código:
A1;aaaaaaaa;10;hgjgjkhgk;
A2;aaaabahdhdhdhd;11;hGJHGJH;
A3;tuytuytu;20;yyuLJLKjl_kiui;
B1;wwwwww;21;6876876;
C3;zzzzzzzzzzzzzzzzzzzz;50;40;rerhgHGFH787;


El fichero DOS tiene
Código:
A1;aaaaaaaa;7000;TTTTTTTTTTT;QQQQQQQQQQQQ;1000;
A2;bbbbnnnHtht;600;WWWWWWW;ASASASASA;1001;
B1;TYTYTYTYT;170;NNNNNNNNNNN;VBVBVBVBVB;1002;


La clave es el 1er campo: A1, A2, A3, B1 y C3.

Según este ejemplo el fichero de salida debe tener sólo:
Código:
A3;tuytuytu;20;yyuLJLKjl_kiui;
C3;zzzzzzzzzzzzzzzzzzzz;50;40;rerhgHGFH787;

Por que ambos no están en fichero DOS.

No sé si me he explicado bien.

Muchas Gracias por vuestra ayuda
Mensaje Jue Ene 24, 2008 7:18 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4130
Ubicación: Valladolid, España
Responder citando

Ha quedado claro con el ejemplo: sacar las claves de UNO que no están en DOS.

Esta es una forma de hacerlo

Perl:
#!/usr/bin/perl

# Leemos ficheros y lo pasamos a hash,
# siendo la clave el primer campo de la línea
my %uno = map { (split q{;})[0] => $_ } do { open F, "<uno"; <F> };
my %dos = map { (split q{;})[0] => $_ } do { open F, "<dos"; <F> };

# Sacamos las diferencias entre los dos
foreach my $uno ( keys %uno ) {
    print $uno{$uno}                    # Saca la línea de 'uno'
        if not $dos{$uno};              #    si no existe esa clave en 'dos'
}



Otra solución interesante sería usar el módulo List::Compare.

P.D. Esta solución es del foro Experto.
Mensaje Jue Ene 24, 2008 7:28 am
danimera
Perlero Adicto
Perlero Adicto
Registrado: 23 Jun 2005
Mensajes: 239
Ubicación: Colombia
Responder citando

mmmmmm Yo pasaría todo el fichero a un arreglo y lo compararía línea por línea. No sé si funcionará

Perl:

#!/usr/bin/perl

#Abrimos los ficheros

open (DATABASE, "<$fichero1") || &error('abrir','archivo');
flock (DATABASE,1)||&error('lock','file');
@registros1 = <DATABASE>;
close (DATABASE) || &error('cerrar','archivo');

open (DATABASE, "<$fichero2") || &error('abrir','archivo');
flock (DATABASE,1)||&error('lock','file');
@registros2 = <DATABASE>;
close (DATABASE) || &error('cerrar','archivo');

foreach $a(@resgistros1){

     foreach $b(@resgistros2)  print $_ if $a eq b; # caturo los que son iguales
}



Aunque también hice un módulo para trabajar con ficheros. Es sencillo pero tiene algunas funcionalidades interesantes ^^
Mensaje Jue Ene 24, 2008 8:38 am
chemaff
Perlero Nuevo
Perlero Nuevo
Registrado: 21 Ene 2008
Mensajes: 4
comparar ficheros .csv por un campo clave Responder citando

Muchas Gracias por las soluciones.
Había encontrado una solución por mi mismo pero es "un poco" más larga.
Probaré estas soluciones, espero entenderlas, en especial la de Explorer, está más allá de mis conocimientos actuales de Perl.

Muchas gracias. Very Happy
Publicar nuevo tema   Responder al tema    Foros de discusión -> Experto Todas las horas son GMT - 6 Horas
Página 1 de 1



Powered by phpBB © 2001, 2005 phpBB Group