
Quiero comparar dos archivos con el mismo número de filas y columnas con registros en el mismo orden. Solo quiero resaltar las diferencias en los valores de las columnas, si las hay.
file A
:
1,kolkata,19,ab
2,delhi,89,cd
3,bangalore,56,ef
file B
:
1,kolkata,21,ab
2,mumbai,89,gh
3,bangalore,11,kl
Considerando la columna 1
como clave principal, tenemos diferencias en otras columnas. Quiero resaltar esas diferencias.
El formato de salida puede ser (no estoy seguro):
record_number, columns_with_diff
1 3
2 2,4
3 3,4
¿Puede diff
o comm
solucionar mi problema? En caso afirmativo, ¿cuál sería el comando exacto?
Respuesta1
Esto sería todo. Sólo un problema de estilo con la coma adicional al final de cada línea.
awk '
BEGIN{ FS=","; ORS="" }
{
# read line from secondary file
getline aux < "file2"
split(aux,f2,",")
# print current line number
print NR" "
# process each field in current line
for(i=1; i<=NF; i++) {
if ($i!=f2[i]) {
print i","
}
}
print "\n"
}
' file1
La salida:
1 3,
2 2,4,
3 3,4,
Respuesta2
Puedes hacerlo más fácil con perl
:
$ perl -F',' -anle '
BEGIN{
print "record_number, columns_with_diff";
$" = ",";
}
if (!defined($h{$.})) {
@{$h{$.}}{0..$#F} = @F[0..$#F];
} else {
@diff = grep { $h{$.}{$_} ne $F[$_] } 0..$#F;
print "$.\t\t@{[map {$_+1} @diff]}";
}
close ARGV if eof;
' file1 file2
record_number, columns_with_diff
1 3
2 2,4
3 3,4
Debe eliminar las líneas en blanco en su entrada para que esto funcione.
Explicación
En
BEGIN
el bloque simplemente imprimimos el encabezado de la salida, luego configuramos el separador de lista en,
@{$h{$.}}{0..$#F} = @F[0..$#F]
: creamos un hash de hashes con las claves del primer hash que son el número de línea, cada subhashes tiene las claves que son el índice del campo menos 1 y los valores son valores que corresponden a esos campos.
Aquí usamos un segmento hash para asignar rápidamente valores al hash de hashes.
Si usas Data::Dumper
para imprimir el hash de hashes %h
, puedes ver algo como esto:
VAR1 = {
'2' => {
'2' => '89',
'0' => '2',
'1' => 'delhi',
'3' => 'cd'
},
'3' => {
'1' => 'bangalore',
'3' => 'ef',
'0' => '3',
'2' => '56'
},
'1' => {
'3' => 'ab',
'1' => 'kolkata',
'0' => '1',
'2' => '19'
}
};
Si hemos creado
%h
(if (!defined($h{$.}))
), lo que significa que terminamos de procesarfile1
, simplemente comparamos cada campo de la línea actual con el valor de respuesta central%h
, almacenando todos los índices diferentes en la matriz@diff
.map {$_+1} @diff
restaure el número de columna, porque el índice de la matriz comienza en 0, el número de columna comienza en 1.close ARGV if eof
restaurar$.
contador.