Compare a primeira coluna em arquivos diferentes [closed]

1

Eu quero comparar um arquivo com outros arquivos no mesmo diretório.

file1.txt contém:

move 34#123#    
get 11#278    
put 33#29#567#23

file1.txt deve comparar com os arquivos 1.txt e 2.txt .

1.txt contém:

move 11    
put 34    
run 13

2.txt contém:

get 14    
move 66

Eu preciso que os resultados sejam assim:

move 2    
get 1    
put 1

Como posso conseguir isso?

    
por Rincy Raphael 21.04.2014 / 08:34

3 respostas

4

Aqui está uma solução awk :

$ awk 'FNR==NR{a[$1];next}($1 in a){++a[$1]}
    END{for(i in a){print i" "a[i]}}' file1.txt 1.txt 2.txt
put 1
get 1
move 2

Explicação

  • FNR==NR{a[$1];next} : ao processar file1.txt , marcamos a ocorrência de $1 na matriz associativa a .
  • ($1 in a){++a[$1]} : ao processar 1.txt e 2.txt , verificamos se $1 existe no array associativo a , se sim, aumentando a contagem em 1.
  • Finalmente, percorra a matriz associativa a , imprima a chave (primeiro campo nos arquivos) e seu valor (número de ocorrências em 1.txt e 2.txt ).

Aqui está outra solução em perl , com a mesma lógica:

$ perl -alne '++$i;                  
    if ($. == $i) {
        $h{$F[0]}=0;
        close ARGV if eof;
        next;
    }
    ++$h{$F[0]} if defined $h{$F[0]};
END {
    for (keys %h) {
        print $_." ".$h{$_};
    }
}' file1.txt 1.txt 2.txt
move 2
get 1
put 1
    
por 21.04.2014 / 08:48
1

Mostrando uma alternativa que usa várias ferramentas, grep , awk , sort , & %código%. Concedido faz uso de mais ferramentas, mas acho mais fácil entender o que está acontecendo contra o AWK.

$ for i in 1.txt 2.txt; do grep -f <(awk '{print $1}' $i) file1.txt; done | \
    awk '{print $1}' | sort | uniq -c

Exemplo

$ for i in 1.txt 2.txt; do grep -f <(awk '{print $1}' $i) file1.txt; done | \
    awk '{print $1}' | sort | uniq -c
      1 get
      2 move
      1 put

Como funciona

Aqui está o exemplo desenrolado um pouco.

$ for i in 1.txt 2.txt; do 
    grep -f <(awk '{print $1}' $i) file1.txt
  done | \
    awk '{print $1}' | sort | uniq -c

O loop uniq passa pelos dois arquivos com os quais estamos combinando, for e 1.txt . Cada vez que passamos pelo loop, estamos usando a primeira coluna de um desses arquivos como um conjunto estático de strings para 2.txt procurando por elas em nosso arquivo de destino, grep . Esta é a linha que faz isso:

$ grep -f <(awk '{print $1}' $i) file1.txt

Depois de executar isso usando cada arquivo do loop file1.txt , pegamos toda a saída e selecionamos apenas a primeira coluna:

move
put
move
get

Em seguida, usamos for e sort para calcular quantos de cada tipo vimos.

    
por 21.04.2014 / 08:56
0

Aqui está outra maneira com join :

join -1 1 -2 2 -o 0 2.1 <(sort -k1,1 file1.txt) <(cut -d ' ' -f1 1.txt 2.txt | sort | uniq -c)

observe que a saída será classificada:

get 1
move 2
put 1

Se você quiser preservar a ordem de file1.txt , por exemplo,

move 2
get 1
put 1

você pode executar:

join -j2 -o 1.1 0 2.1 <(nl -ba -nrz file1.txt | sort -k2,2) \
<(cut -d ' ' -f1 1.txt 2.txt | sort | uniq -c) | sort -k1 | cut -d ' ' -f2-
    
por 26.09.2015 / 15:20