Como vários blocos funcionam no AWK?

2

Eu encontrei este script para me livrar de caracteres de nova linha em um arquivo de texto de largura fixa. A ideia é mudar um arquivo cheio de entradas como:

>IGHV1-18*01
CAGGTTCAGCTGGTGCAGTCTGGAGCTGAGGTGAAGAAGCCTGGGGCCTCAGTGAAG
GTCTCCTGCAAGGCTTCTGGTTACACCTTTACCAGCTATGGTATCAGC
TGGGTGCGACAGGCCCCTGGACAAGGGCTTGAGTGGATGGGATGGATCAGCGCTTAC
AATGGTAACACAAACTATGCACAGAAGCTCCAGGGCAGAGTCACCATGACCACA
GACACATCCACGAGCACAGCCTACATGGAGCTGAGGAGCCTGAGATCTGACGACACGGCC
GTGTATTACTGTGCGAGAGA

para

>IGHV1-18*01
CAGGTTCAGCTGGTGCAGTCTGGAGCTGAGGTGAAGAAGCCTGGGGCCTCAGTGAAGGTCTCCTGCAAGGCTTCTGGTTACACCTTTACCAGCTATGGTATCAGCTGGGTGCGACAGGCCCCTGGACAAGGGCTTGAGTGGATGGGATGGATCAGCGCTTACAATGGTAACACAAACTATGCACAGAAGCTCCAGGGCAGAGTCACCATGACCACAGACACATCCACGAGCACAGCCTACATGGAGCTGAGGAGCCTGAGATCTGACGACACGGCCGTGTATTACTGTGCGAGAGA

Eu não tenho muita experiência com o AWK, então imaginei que seria uma boa experiência de aprendizado tentar decifrá-lo. No entanto, estou com dificuldades. Especificamente sobre vários blocos próximos uns dos outros, o primeiro bloco é um loop implícito?

awk '/^>/ {printf("\n%s\n",$0);next; } { printf("%s",$0);}  END {printf("\n");}' < file.fa
    
por posdef 09.09.2016 / 14:42

2 respostas

3

Sim, sim. Só não é implícito. O formato é realmente:

/foo/{something}

Qual é o mesmo que

if(/foo/){something}

Em outras palavras, se a linha atual corresponder a foo (no seu exemplo, se corresponder a > ), imprima uma nova linha, a linha atual e outra nova linha.

O next garante que, se o primeiro bloco for executado, o script pula o restante dos blocos e passa para a próxima linha. O oneliner também pode ser escrito assim:

awk '{
        if(/^>/){
            printf("\n%s\n",$0);
        }
        else{ 
            printf("%s",$0);
        }
        END {
                printf("\n");
        }' < file.fa

Por fim, como a simples chamada print de awk adiciona uma nova linha, você pode usar uma versão um pouco mais simples:

awk '/^>/{print "\n"$0;next;}{printf("%s",$0);} END{print}' file.fa
    
por 09.09.2016 / 14:56
3

awk irá ler, linha por linha (você pode considerar como um bloco, mas é uma linha, terminando por line-feed ou CR)

vamos quebrar esse código

awk '/^>/ {printf("\n%s\n",$0);next; } { printf("%s",$0);}  END {printf("\n");}'

Como você pode ver em man awk , programas awk estão na forma de /pattern/ { actions} , assim o programa se transforma em:

  • /^>/ {printf("\n%s\n",$0);next; }

    • para linhas que começam com > ( /^>/ )
    • imprima a linha cercada por \n ( printf("\n%s\n",$0) )
    • busque a próxima linha ( next ), não vá para o próximo comando awk.
  • { printf("%s",$0);}

    • para todos os padrões (a cláusula padrão está vazia)
    • linha de impressão sem um caractere de nova linha ( printf("%s",$0); )
  • END {printf("\n");}

    • após o final do arquivo (ou arquivos) ( END )
    • imprima uma nova linha ( printf "\n" ; )
por 09.09.2016 / 14:55

Tags