Comparação entre dois arquivos separados por tabulações no shell script usando o awk

5

Eu escrevi este código, mas estou enfrentando o problema, conforme mencionado abaixo.

Meu código é:

paste 1.txt   2.txt|
awk ' { FS = "\t " } ; NR == 1 { n = NF/2 }
              {for(i=1;i<=n;i++)
                 if($i!=$(i+n))
                   {c = c s i; s = "," }
               if(c)
                 {print "Line No. " NR-1 " COLUMN NO " c;
                  c = "" ; s = "" } } '

Resultado esperado:

Line No. 2 COLUMN NO 2,3
Line No. 4 COLUMN NO 1,2,3,4
Line No. 6 COLUMN NO 2,3,4,5
Line No. 7 COLUMN NO 1,2,3,4,5

Saída que está sendo gerada:

Line No. 2 COLUMN NO 2,3
Line No. 4 COLUMN NO 1,2,3,4
Line No. 6 COLUMN NO 2,3,4,5
Line No. 7 COLUMN NO 1,2,3,4

Abaixo do arquivo especificado está separado por espaço. Para entender melhor, eu formatei desta maneira.

Arquivo1:

ID_ID   First_name  Last_name Address                      Contact_Number
ID1     John        Rock      32, Park Lake, California    2222200000
ID2     Tommy       Hill      5322 Otter Lane Middleberge  3333300000
ID3     Leonardo    Test      Half-Way Pond, Georgetown    4444400000
ID8     Rhyan       Bigsh     6762,33 Ave N,St. Petersburg 5555500000
ID50    Steve       Goldberg  6762,33 Ave N,St. Petersburg 6666600000
ID60    Steve       Goldberg                               6666600000

Arquivo2:

ID_ID   First_name  Last_name   Address                      Contact_Number
ID1     John        Rock        32, Park Lake, California    2222200000
ID2     Tommy1      Hill1       5322 Otter Lane Middleberge  3333300000
ID3     Leonardo    Test        Half-Way Pond, Georgetown    4444400000
ID80    Sylvester   Stallone                                 5555500000
ID50    Steve       Goldberg    6762,33 Ave N,St. Petersburg 6666600000
ID60    Mark        Waugh       St. Petersburg               7777700000
ID70    John        Smith                                    8888800000
    
por Vishal Jain 07.03.2017 / 08:05

1 resposta

2

Aqui está uma sugestão. A saída de:

paste 1.txt 2.txt | awk '
{ FS = "\t" }
NR == 1 { n = NF/2 } {
  for(i=1;i<=n;i++) print "\"" $i "\" " ($i == $(i+n) ? "==":"!=") " \"" $(i+n) "\""
  print "###############"
}'

que compara e imprime todos os campos em todos os registros entre arquivos, termina com:

"ID60" == "ID60"
"Steve" != "Mark"
"Goldberg" != "Waugh"
"" != "St. Petersburg"
"6666600000" != "7777700000"
###############
"" != "8888800000"
"ID70" != ""
"John" != ""
"Smith" != ""
"" == ""
###############

Existem dois erros:

  1. Existe um erro oculto off-by-one no caso de uma linha existente apenas no segundo arquivo. Isso ocorre porque um registro ausente possui um campo, uma string vazia antes da guia adicionada por paste . Portanto, neste caso, você está efetivamente comparando os campos na ordem 5,1,2,3,4.

  2. O campo 4 está vazio para esta linha em ambos os arquivos (embora de maneiras diferentes), então eu teria esperado a saída:

    Line No. 7 COLUMN NO 1,2,3,5

Para obter a saída exata desejada, a correção básica abaixo relatará que todos os campos não correspondem se uma linha estiver presente apenas em um arquivo. Isso pode ser detectado pelo NF == n+1 adicionado ao if , porque deve haver apenas n+1 e não 2*n campos para uma linha apenas presente em um arquivo, o arquivo que for.

paste 1.txt 2.txt | awk '
{ FS = "\t" }
NR == 1 { n = NF/2 } {
  for(i=1;i<=n;i++) if(NF == n+1 || $i!=$(i+n)) {c = c s i; s = "," }
  if(c){print "Line No. " NR-1 " COLUMN NO " c; c = "" ; s = "" }
}'

Isso pressupõe que todos os registros contenham o número correto de guias, n-1 .

    
por Martin Thornton 06.04.2017 / 16:32