
Quero comparar dois arquivos com o mesmo número de linhas e colunas com registros na mesma ordem. Quero apenas destacar as diferenças nos valores das colunas, se houver.
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 a coluna 1
como chave primária, temos diferenças nas demais colunas. Quero destacar essas diferenças.
O formato de saída pode ser (não tenho certeza):
record_number, columns_with_diff
1 3
2 2,4
3 3,4
Pode diff
ou comm
resolver meu problema? Se sim, qual seria o comando exato?
Responder1
Seria isso. Apenas algum problema de estilo com a vírgula extra no final de cada linha.
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
A saída:
1 3,
2 2,4,
3 3,4,
Responder2
Você pode fazer isso mais facilmente com 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
Você deve remover linhas em branco em sua entrada para que isso funcione.
Explicação
No
BEGIN
bloco, apenas imprimimos o cabeçalho da saída e definimos o separador de lista como,
@{$h{$.}}{0..$#F} = @F[0..$#F]
: criamos um hash de hashes com as chaves do primeiro hash são o número da linha, cada sub hashes tem as chaves são o índice do campo menos 1, e os valores são valores que correspondem a esses campos.
Aqui usamos uma fatia de hash para atribuir valores rapidamente ao hash de hashes.
se você usar Data::Dumper
para imprimir o hash dos hashes %h
, poderá ver algo assim:
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'
}
};
Se criamos
%h
(if (!defined($h{$.}))
) - o que significa que terminamos o processamentofile1
- apenas comparamos cada campo da linha atual com o valor coresspond em%h
, armazenando todos os índices diferentes no array@diff
.map {$_+1} @diff
restaure o número da coluna, porque o índice da matriz começa em 0, o número da coluna começa em 1.close ARGV if eof
restaurar$.
contador.