imprimir apenas linhas que contenham apenas uma cópia de um valor na primeira coluna

0

Eu tenho um monte de arquivos, e cada um parece assim:

HWI-ST913:300:C5W5DACXX:7:1101:1477:2147    Ha1_00044161    80.6    31  6   0   94  2   1   31  5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:1629:2128    Ha6_00047653    90.9    33  3   0   2   100 173 205 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:1649:2180    Ha9_00011743    100.0   33  0   0   100 2   274 306 7.8e-12 65.9
HWI-ST913:300:C5W5DACXX:7:1101:1649:2180    Ha5_00006578    100.0   33  0   0   100 2   98  130 7.8e-12 65.9
HWI-ST913:300:C5W5DACXX:7:1101:1649:2180    Ha12_00033467   100.0   33  0   0   100 2   91  123 7.8e-12 65.9
HWI-ST913:300:C5W5DACXX:7:1101:6099:2062    B2KZF9_PICAB    100.0   33  0   0   1   99  73  105 2.4e-13 70.9
HWI-ST913:300:C5W5DACXX:7:1101:6891:2170    Ha2_00026275    87.9    33  4   0   2   100 27  59  9.3e-13 68.9
HWI-ST913:300:C5W5DACXX:7:1101:6891:2170    Ha13_00015465   87.9    33  4   0   2   100 884 916 9.3e-13 68.9
HWI-ST913:300:C5W5DACXX:7:1101:6891:2170    Ha17_00009154   87.9    33  4   0   2   100 420 452 9.3e-13 68.9

Eu quero manter apenas as linhas onde a primeira coluna é única. Esta é a minha saída desejada:

HWI-ST913:300:C5W5DACXX:7:1101:1477:2147    Ha1_00044161    80.6    31  6   0   94  2   1   31  5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:1629:2128    Ha6_00047653    90.9    33  3   0   2   100 173 205 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:6099:2062    B2KZF9_PICAB    100.0   33  0   0   1   99  73  105 2.4e-13 70.9
    
por Anna1364 27.01.2018 / 01:17

5 respostas

3

A abordagem do KISS em awk : mantém uma matriz das linhas e uma das contagens - depois imprime apenas as linhas cuja contagem é 1 no final:

awk '{a[$1]=$0; c[$1]++} END{for (i in a) {if (c[i] == 1) print a[i]}}' file

Como alternativa, se você tiver uma versão de uniq que suporte a opção -w ( --check-chars ) e:

  1. seus dados são classificados no primeiro campo; e

  2. a largura do primeiro campo é constante

você pode usar isso:

uniq -uw 40 file
HWI-ST913:300:C5W5DACXX:7:1101:1477:2147    Ha1_00044161    80.6    31  6   0   94  2   1   31  5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:1629:2128    Ha6_00047653    90.9    33  3   0   2   100 173 205 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:6099:2062    B2KZF9_PICAB    100.0   33  0   0   1   99  73  105 2.4e-13 70.9

Isso tem a vantagem de preservar a ordem do arquivo original, se isso for importante para sua aplicação.

    
por 27.01.2018 / 01:42
2

Uma abordagem pode ser isso. Requer dupla análise do mesmo arquivo, mas os resultados são impressos em ordem:

$ awk 'NR==FNR{f1[$1]++;next}f1[$1]==1' file1 file1
HWI-ST913:300:C5W5DACXX:7:1101:1477:2147    Ha1_00044161    80.6    31  6   0   94  2   1   31  5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:1629:2128    Ha6_00047653    90.9    33  3   0   2   100 173 205 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:6099:2062    B2KZF9_PICAB    100.0   33  0   0   1   99  73  105 2.4e-13 70.9
    
por 27.01.2018 / 01:34
1

Dado apenas que os arquivos de entrada são classificados, o seguinte funcionará em qualquer sistema compatível com POSIX:

sed 's/ .*//' file.txt | uniq -u | join - file.txt

Se os separadores de espaço forem realmente tabulações no documento original, você poderá substituir a chamada sed por cut -f1 file.txt e deixar o restante igual.

    
por 27.01.2018 / 01:37
0

você pode fazer isso com sort , com a opção -k para especificar quais campos você deseja considerar para a classificação.

sort -k 1,1 -u <file>

ou com o awk, usando -F para delimitar campos e ignorar quaisquer linhas duplicadas em _ .

awk -F' ' '!_[$1]++' <file>

Isso imprimirá a linha inteira para cada primeira ocorrência de um valor na primeira coluna. Em seu texto de amostra, esses dois comandos seriam exibidos:

HWI-ST913:300:C5W5DACXX:7:1101:1477:2147    Ha1_00044161    80.6    31  6   0   94  2   1   31  5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:1629:2128    Ha6_00047653    90.9    33  3   0   2   100 173 205 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:1649:2180    Ha9_00011743    100.0   33  0   0   100 2   274 306 7.8e-12 65.9
HWI-ST913:300:C5W5DACXX:7:1101:6099:2062    B2KZF9_PICAB    100.0   33  0   0   1   99  73  105 2.4e-13 70.9
HWI-ST913:300:C5W5DACXX:7:1101:6891:2170    Ha2_00026275    87.9    33  4   0   2   100 27  59  9.3e-13 68.9

EDIT: atualizado para considerar instâncias verdadeiramente exclusivas da coluna 1, não para a desduplicação

awk '{col1[$1]++; !lines[$1] && lines[$1]=$0} 
     END { for (key in col1) if (col1[key]==1) print lines[key] }' <file>

resultaria em:

HWI-ST913:300:C5W5DACXX:7:1101:1629:2128    Ha6_00047653    90.9    33  3   0   2   100 173 205 5.1e-11 63.2
HWI-ST913:300:C5W5DACXX:7:1101:6099:2062    B2KZF9_PICAB    100.0   33  0   0   1   99  73  105 2.4e-13 70.9
HWI-ST913:300:C5W5DACXX:7:1101:1477:2147    Ha1_00044161    80.6    31  6   0   94  2   1   31  5.1e-11 63.2
    
por 27.01.2018 / 01:29
0

Para que apenas uma varredura do arquivo e imprima as linhas uniq na mesma ordem que o arquivo de entrada, use:

No GNU awk (para usar "sorted_in" para garantir uma varredura ordenada da matriz): use três matrizes:

  1. Um para contar linhas repetidas (c []),
  2. um para a ordem de classificação das linhas (s []) e
  3. um para as linhas próprias (v [])

No final, imprima apenas as linhas cuja contagem é 1.

awk 'BEGIN { PROCINFO["sorted_in"] = "@ind_num_asc" ; i=0}
        !c[$1]++{s[++i]=$1;v[i]=$0}
     END{for(i in v){if(c[s[i]]==1){print v[i]}}}' infile

Observe que !c[$1]++ capturará apenas a primeira aparição do primeiro campo

    
por 27.01.2018 / 04:01