Muchísimas gracias por la respuesta, explorer, pero llevo cuatro días con Perl y me cuesta un poco entenderlo. Mejor te explico lo que quiero hacer y te dejo el código que tengo:
Tengo dos archivos bastante grandes con campos separados por tabulaciones, uno con tres campos ($A1, $A2 y $A3) y el otro con dos ($B1 y $B2).
Quiero comparar $A2 con $B1, y si coinciden, imprimir en otro archivo $A1, $B2 y $A3.
$A2 y $B1 son huellas de archivos MD5, por lo tanto tienen formato hexadecimal.
Esto es lo que yo he hecho para compararlos de una manera "eficiente" (crean 16
hashes por cada archivo usando la inicial):
Using perl Syntax Highlighting
use strict;
use warnings;
use Time::HiRes qw(time);
my $inicio = time();
my $entrada = Archivo1;
chomp($entrada);
open( ENTRADA, "$entrada" ) or die "Error: No se puede abrir $entrada!";
my @entrada = <ENTRADA>;
close(ENTRADA);
my $entrada2 = Archivo2;
chomp($entrada2);
open( ENTRADA, "$entrada2" ) or die "Error: No se puede abrir $entrada2!";
my @entrada2 = <ENTRADA2>;
close(ENTRADA2);
my $salida = Resultado;
chomp($salida);
open( SALIDA, ">>$salida" ) or die "Error: No se puede abrir $salida!";
my @salida;
# Definir 16 hashes para cada archivo de entrada (0 - F)
my %A_0;
my %A_1; # Así hasta my %A_F;
my %B_0;
my %B_1; # Así hasta my %B_F;
# Dividir las líneas y llenar los hashes dependiendo de la letra inicial (@entrada1)
for ( my $i = 0; $i < 16; $i++ ) {
foreach my $linea (@entrada) {
chomp($linea);
( my $A1, my $A2, my $A3 ) = split( /\t/, $linea );
my $HEX = sprintf( "%x", $i );
my $primer = substr( $A2, 0, 1 );
if ( $primer eq "0" ) { $A_0{$A2} = "$A1 $A3"; }
if ( $primer eq "1" ) { $A_1{$A2} = "$A1 $A3"; }
# Corto para no ocupar tanto espacio...
if ( $primer eq "f" ) { $A_F{$A2} = "$A1 $A3"; }
}
}
# Dividir las líneas y llenar los hashes dependiendo de la letra inicial (@entrada2)
for ( my $i = 0; $i < 16; $i++ ) {
foreach my $linea (@entrada2) {
chomp($linea);
( my $B1, my $B2 ) = split( /\t/, $linea );
my $HEX = sprintf( "%x", $i );
my $primer = substr( $B1, 0, 1 );
if ( $primer eq "0" ) { $B_0{$B1} = $B2; }
if ( $primer eq "1" ) { $B_1{$B1} = $B2; }
# Corto para no ocupar tanto espacio...
if ( $primer eq "f" ) { $B_F{$B1} = $B2; }
}
}
# Comparar %A_0 con %B_0
foreach my $clave ( keys %A_0 ) {
( my $A1, my $A3 ) = split( /\t/, $A_0{$clave} );
foreach my $clave2 ( keys %B_0 ) {
my $B2 = "$B_0{$clave2}";
if ( $clave eq $clave2 ) {
push( @salida, "$A1 $B2 $A3\n" );
delete $A_0{$clave};
delete $B_0{$clave2};
}
}
}
# Y seguir comparando el resto de hashes (%A_1 con %B_1, %A_2 con %B_2)...
# Por ultimo imprimir los resultados
open( SALIDA, ">>$salida" ) or die "Error: No se puede escribir en $salida!";
foreach my $linea (@salida) {
chomp($linea);
print SALIDA "$linea\n";
}
close(SALIDA);
my $fin = time();
print "\n\n Finalizado en ", ( $fin - $inicio ), " segundos.\n";
Coloreado en 0.003 segundos, usando
GeSHi 1.0.8.4
Con este código, digamos que copio, pego y modifico los nombres 16 veces (no me importa). Pero si en lugar de usar una sola letra, quiero hacerlo con las 2 primeras tengo que hacerlo 256 veces
, por eso decía que si se podía hacer con for().
Muchas gracias, explorer, sobre todo por los comentarios del código.
PD:
- "say" es como "print", ¿no?
- Si se hace un sort() de los
hashes ¿sería más rápido al compararlos (a pesar de lo que tarde en ordenarlo)?