Script AWK para comparar o conteúdo de 2 arquivos

1

Eu tenho 2 arquivos ..

arquivo1:

abc|123|check
def|456|map
ijk|789|globe
lmn|101112|equator

arquivo2:

check
map
equator
globe 

A função AWK deve comparar a 3ª coluna (depois de cortar a 3ª coluna e a classificação) do arquivo1 comparando com o conteúdo classificado como arquivo2

  • deve retornar 1 se TODAS as linhas estiverem correspondendo
  • else deve retornar 2
por Nandini 06.05.2015 / 03:32

3 respostas

1

function are_all_there {
    local num_diff=$(comm -3 <(cut -d'|' -f3 "$1" | sort) <(sort "$2") | wc -l)
    (( num_diff == 0 )) && return 1 || return 2
}
    
por 06.05.2015 / 12:22
0

Com base nos seus comentários, parece que awk não é sua única opção. então aqui está um método não-awk.
Você não menciona a necessidade de uma comparação exclusiva na pergunta, mas usou uniq no exemplo em seu comentário. Se você não precisa de uma correspondência exclusiva , basta remover a opção -u da classificação. (testado em bash ) .

(($(comm -3 <( cut -d'|' -f3 file1 | sort -u ) \
            <( sort -u file2 ) | wc -l))) && echo 2 - not all match ||
                                             echo 1 - all match

Ou usando awk para a comparação final - com um pouco de ajuda de paste .

paste <( cut -d'|' -f3 file1 | sort -u ) \
      <( sort -u file2 ) |
   awk '$1!=$2{m=2; exit} 
     END{ if(m == 2){print "2 - not all match"; exit;} 
                     print "1 - all match";}' 

Ou, awk comparação de dois arquivos de entrada

 awk '{if(NR == FNR){a[NR]=$1}
       else{ if($1 != a[NR]){m=2; exit}}}  
      END{ if(m == 2){print "2 - not all match"; exit;} 
                      print "1 - all match";}' \
    <( cut -d'|' -f3 file1 | sort -u ) \
    <( sort -u file2 ) |
    
por 06.05.2015 / 11:38
0

Divertido CS responde! Na verdade, não temos que classificar nada, porque essa é uma comparação de conjunto pura.

Os arquivos de entrada são representação de um conjunto no qual os elementos são pares. Por exemplo, se a linha foo ocorrer 3 vezes em file1 , isso representa o elemento < foo , 3 & gt ;. Se file2 contiver foo 3 vezes, isso significa que ambos os conjuntos contêm esse elemento. Se file2 não contiver foo ou contiver um número diferente de repetições de foo , então ele representa um conjunto que não contém < foo , 3 >.

Além disso, observe que um conjunto de pares como < foo , 3 > pode ser representado por um hash que mapeia a chave foo para 3.

Macro awp do TXr Lisp:

(awk (:begin (set fs "|"))
     (:let (h1 (hash :equal-based)) (h2 (hash :equal-based)))
     ((= arg 1) (inc [h1 [f 2] 0]))
     ((= arg 2) (inc [h2 rec 0]))
     (:end (exit (equal h1 h2))))

Isso produz um status de finalização bem-sucedido se os arquivos forem iguais na forma necessária, caso contrário, um status com falha:

$ txr comp.tl file1 file2
$ echo $?
0
$ echo map >> file2
$ txr comp.tl file1 file2
$ echo $?
1

Se quisermos complicar as coisas para o programa de chamada fazendo com que ele analise a saída "1" ou "2", isso pode ser feito alterando a regra :end :

(:end (prn (if (equal h1 h2) "1" "2")))

Aqui está como as coisas parecem no awk normal. A principal diferença é que temos uma sintaxe concisa, na qual não precisamos definir nenhuma variável a que nos referimos; por outro lado, temos que escrever um par de loops para comparar dois arrays associativos e gerar nossa própria variável arg para rastrear qual arquivo estamos processando. (GNU Awk tem o ARGIND para este propósito.)

BEGIN { FS = "|" }
FNR == 1 { arg++ }
arg == 1 { h1[$3]++; }
arg == 2 { h2[$0]++; }
END { same = 1
      for (i in h1)
        if (h1[i] != h2[i]) {
          same = 0
          break
        }
      if (same)
        for (i in h2)
          if (h2[i] != h1[i]) {
            same = 0
            break
          }
      print same ? "1" : "2"; }
    
por 13.09.2016 / 18:10