awk - pula a primeira linha do registro

0

Eu verifiquei os diferentes tópicos, mas não consegui encontrar uma solução para o meu problema. Eu tenho um arquivo contendo uma seqüência de letras A, T, C, G (representando seqüências de DNA) da seguinte forma:

$ cat species_gene

>genus_1_species_1
TTGGATATTGAGTTACATACATATGATTTGGGAATGGAGAACCGAGATAAGACTGAAGATCAAGTCACAATTGATTGTGC
TAATGCTGTCAAGAAATACAATGTCGGCATCAAATGTGCAACTATTACTCCTGATGAAAATCGAGTTGAGGAGTTCAAGC

>tribe_1_species_1
CTGGATATAGAGTTGCACACATACGATCTGGGAATGGAAAACCGCGACAAGACTGATGACCAAGTCACAATCGATTGCGC
CAACGCGATTAAAAAATACAACGTTGGAATTAAGTGCGCGACCATCACTCCCGACGAGAAGAGAGTCGAGGAATTCAAGC

>species_2
CTTGATATTGAACTACACACCTATGATTTGGGAATGGAATACCGCGATAAAACTGATGACCAAGTCACAATTGACTGCGC
KAATGCTATTAAGAAATACAATGTTGGTATTAAGTGCGCTACCATAACTCCAGATGAAAAAAGAGTTGAAGAATTCAAAC

Eu gostaria de contar o número de letras nas strings após o cabeçalho "> genus_1_species_1" até o próximo cabeçalho. Nesse caso, o comprimento das seguintes seqüências de caracteres, igual a 160:

TTGGATATTGAGTTACATACATATGATTTGGGAATGGAGAACCGAGATAAGACTGAAGATCAAGTCACAATTGATTGTGC     TAATGCTGTCAAGAAATACAATGTCGGCATCAAATGTGCAACTATTACTCCTGATGAAAATCGAGTTGAGGAGTTCAAGC

Eu gostaria de usar o awk e usar ">" como Separador de Registros e quebras de linha como Separador de Campo e, subsequentemente, conta o número de campos (ou seja, linhas), iniciando a partir da segunda linha do registro. Eu usei o seguinte comando:

$ awk 'BEGIN {RS=">"} NR==2 {print length}' species_gene

Eu obtive 180 (o número de caracteres do primeiro registro). A saída que eu gostaria de obter é 160 (o comprimento do primeiro registro, a partir da segunda linha). Eu tentei o seguinte para descartar o cabeçalho:

$ awk 'BEGIN {RS=">"; FS="\n"} NR==2 {if (NF!=1) {length}}' species_gene

Há algo que eu não entendo aqui e ficaria feliz se alguém pudesse me ajudar.

    
por jibbah 13.09.2016 / 03:39

3 respostas

1

IMHO seria mais natural usar a linha em branco como separador de registro. Neste 'modo de parágrafo', o awk inclui novas linhas como separadores de campo, portanto, no seu caso, cada linha do registro se torna um campo. Você pode então remover o primeiro campo atribuindo a string vazia a ele; Isso tem um efeito colateral agradável de reavaliar todo o registro com o separador de campo de saída fornecido: definindo isso para a seqüência vazia também, os campos restantes são concatenados. Você pode então simplesmente imprimir o tamanho do registro.

awk 'BEGIN {RS="";OFS=""} NR==1 {$1=""; print length}' species_gene

Teste com sua entrada específica

$ awk 'BEGIN {RS="";OFS=""} NR==1 {$1=""; print length}' species_gene
160
    
por 13.09.2016 / 03:59
1

length não é apenas uma variável no Awk, mas uma função:

$ awk 'BEGIN {RS=">"} NR==2 {print length($2) + length($3)}' species_gene
160

É isso: adicione os comprimentos dos dois campos, em vez de usar o tamanho de todo o registro.

Mais curto:

$ awk 'BEGIN {RS=">"} NR==2 {print length($2 $3)}' species_gene
160

Igualmente longo:

$ awk 'BEGIN {RS=">"} NR==2 && $0 = length($2 $3)' species_gene
160
    
por 13.09.2016 / 06:22
0

Uma possível melhora menor sobre sua melhoria para resposta da steeldriver :

awk -vRS=">" -vOFS="" '$1=="genus_1_species_1" {$1=""; print length;}' species_gene

O -vRS=">" é equivalente a BEGIN {RS=">"} , e da mesma forma com o -vOFS="" . Minha contribuição é que esta versão permite especificar o cabeçalho do registro cujo comprimento, então você não precisa contar registros.

    
por 14.10.2016 / 09:47