Como classificar por linhas ímpares e remover valores repetidos?

Como classificar por linhas ímpares e remover valores repetidos?

Eu tenho o seguinte tipo de arquivo:

transcr_25793 +
YAL039C -
transcr_25793 +
YAL037C-B -
transcr_20649 +
YBL100C -
transcr_7135 +
YBL029C-A -
transcr_11317 +
YBL067C -
transcr_25793 +
YAL038W +
transcr_7135 +
YBL029W +

Eu estava tentando conseguir algo assim:

transcr_7135 +
YBL029C-A -
transcr_7135 +
YBL029W +
transcr_11317 +
YBL067C -
transcr_20649 +
YBL100C -
transcr_25793 +
YAL039C -
transcr_25793 +
YAL037C-B -
transcr_25793 +
YAL038W +

Então, depois, eu estava procurando por algo assim:

transcr_7135 +
YBL029C-A -
YBL029W +
transcr_11317 +
YBL067C -
transcr_20649 +
YBL100C -
transcr_25793 +
YAL039C -
YAL037C-B -
YAL038W +

Eu percorri sorto manual e algumas postagens, mas não consegui encontrar nada que se aproximasse disso, apenas sortusando valores numéricos para obter linhas ímpares...

Responder1

gawkSolução pura :

awk -F_ 'NR%2{i=$2;next}{a[i]=a[i]"\n"$0}
         END{PROCINFO["sorted_in"]="@ind_num_asc";
             for(i in a) printf "%s","transcr_"i""a[i]"\n"}' file

O truque é classificar anumericamente os índices do array com uma pequena ajuda do gawkarray especial PROCINFO.

transcr_7135
YBL029C-A -
YBL029W +
transcr_11317
YBL067C -
transcr_20649
YBL100C -
transcr_25793
YAL039C -
YAL037C-B -
YAL038W +

Aliás, é uma pena que o awk não ofereça uma opção para classificar naturalmente, também conhecido comoclassificação de versão(conforme texto com números).

Responder2

Não é exatamente a ordem de classificação que você mostrou, mas talvez também esteja certo?

$ cat input.txt|paste - -| sort -k1,1V -k2,2| tr "\t" "\n" | awk '{if($0 in line == 0) {line[$0]; print}}'
    transcr_7135 +
    YBL029C-A -
    YBL029W +
    transcr_11317 +
    YBL067C -
    transcr_20649 +
    YBL100C -
    transcr_25793 +
    YAL037C-B -
    YAL038W +
    YAL039C -

EDITAR:

Insira o número da linha e use-o como chave de classificação, deve produzir a saída exata que você deseja:

$ cat input.txt | paste - - | nl | sort -k2,2V -k1,1g | cut -f2- | tr "\t" "\n" | awk '{if($0 in line == 0) {line[$0]; print}}'

Responder3

Com GNU sorte assumindo que as linhas não contêm caracteres TAB:

paste - - < file | sort -V | tr '\t' '\n' | awk '!seen[$0]++'

Ou sort -t$'\t' -sk1,1Vpara preservar a ordem original para entradas com linhas ímpares idênticas, como na saída esperada.

Se você não possui GNU sorte assumindo que as linhas ímpares sempre seguem esse padrão, você pode substituí-lo sort -Vpor sort -k1.9n.

Responder4

Pré e pós-processamento com awk; isso não pressupõe que uma transcrlinha seja seguida por apenas uma Y*linha; também é idempotente - sua saída pode ser canalizada de volta como entrada e dará o mesmo resultado.

awk '{print $0~/^transcr/ ? t=$0 : t" "$0}' /tmp/foo | sort -t_ -k2n -k2 -u | awk '{print (NF > 2) ? $3" "$4 : $0}'
transcr_7135 +
YBL029C-A -
YBL029W +
transcr_11317 +
YBL067C -
transcr_20649 +
YBL100C -
transcr_25793 +
YAL037C-B -
YAL038W +
YAL039C -

informação relacionada