Como contar as últimas colunas duplicadas sem removê-las?

5

Eu tenho um arquivo que contém 4 colunas. Quero comparar as três últimas colunas e contar quantas vezes elas ocorrem sem excluir nenhuma das linhas. Eu só quero que a contagem esteja presente na frente de cada linha.

Meu arquivo é assim:

ID-jacob  4.0  6.0  42.0  
ID-elsa   5.0  8.0  45.0  
ID-fred   4.0  6.0  42.0  
ID-gerard 6.0  8.0  20.0  
ID-trudy  5.0  8.0  45.0  
ID-tessa  4.0  6.0  42.0

Meu resultado desejado é:

3 ID-jacob  4.0  6.0  42.0  
2 ID-elsa   5.0  8.0  45.0  
3 ID-fred   4.0  6.0  42.0  
1 ID-gerard 6.0  8.0  20.0  
2 ID-trudy  5.0  8.0  45.0  
3 ID-tessa  4.0  6.0  42.0

Eu tentei usar sort e uniq, mas isso só me dá a primeira linha por linhas duplicadas:

cat file | sort -k2,4 | uniq -c -f1 > outputfile
    
por Lin 19.03.2015 / 09:27

2 respostas

3

Você pode ter problemas para armazenar arquivos grandes na memória, isso é um pouco melhor, pois armazena apenas linhas correspondentes, depois que o sort fez o trabalho pesado de colocar as linhas em ordem.

# Input must be sorted first, then we only need to keep matching lines in memory
# Once we reach a non-matching line we print the lines in memory, prefixed by count
# with awk, variables are unset to begin with so, we can get away without explicitly initializing
{ # S2, S3, S4 are saved field values
  if($2 == S2 && $3 == S3 && $4 == S4) {
    # if fields 2,3,4 are same as last, save line in array, increment count
    line[count++] = $0;
  } else {
    # new line with fields 2, 3, 4 different
    # print stored lines, prefixed by the count
    for(i in line) {
      print count, line[i];
    }
    # reset counter and array
    count=0;
    delete line;
    # save this line in array, increment count
    line[count++] = $0;
  }

  # store field values to compare with next line read
  S2 = $2; S3 = $3; S4 = $4;
}
END{ # on EOF we still have saved lines in array, print last lines
    for(i in line) {
      print count, line[i];
    }
}  

É costume salvar awk scripts em um arquivo.
Você poderia usar isso ao longo das linhas de sort -k2,4 file | awk -f script

3 ID-fred   4.0  6.0  42.0  
3 ID-jacob  4.0  6.0  42.0  
3 ID-tessa  4.0  6.0  42.0
2 ID-elsa   5.0  8.0  45.0  
2 ID-trudy  5.0  8.0  45.0  
1 ID-gerard 6.0  8.0  20.0  
    
por 19.03.2015 / 11:53
3

Pode ajudar:

awk '{ pop[$1] = $2" "$3" "$4; x[$2" "$3" "$4]++; } END { for (name in pop) { if (pop[name] in x) { print x[pop[name]], name, pop[name]; } } }' file

Cria dois arrays pop e x. No pop nós temos chaves de column1 e value = colum2 "" column3 "" column4, em array x temos valores de chaves de array pop e valores contando repetições. No loop final, verificamos cada nome no valor pop da matriz na matriz x. Isso não preserva seu pedido.

    
por 19.03.2015 / 10:27