Exclui a linha inteira começando com um caractere especial, exceto pela primeira palavra

4

Recentemente, comecei a usar o linux e quase não me dou conta dos comandos sed. Preciso editar um arquivo que contenha um monte de linhas longas começando com o caractere comum ">" e exclua o restante desta linha mantendo apenas a primeira palavra, mas não toque em nenhuma linha que não comece com ">" usando o comando sed.

Em outras palavras, eu preciso transformar isso (apenas uma parte da primeira entrada para fins de demonstração):

>YAL001C TFC3 SGDID:S000000001, Chr I from 151006-147594,151166-151097, Genome Release 64-1-1, reverse complement, Verified ORF, "Largest of six subunits of the RNA polymerase III transcription initiation factor complex (TFIIIC); part of the TauB domain of TFIIIC that binds DNA at the BoxB promoter sites of tRNA and similar genes; cooperates with Tfc6p in DNA binding"
MVLTIYPDELVQIVSDKIASNKGKITLNQLWDISGKYFDLSDKKVKQFVLSCVILKKDIE
VYCDGAIP*

para isso:

>YAL001C
MVLTIYPDELVQIVSDKIASNKGKITLNQLWDISGKYFDLSDKKVKQFVLSCVILKKDIE
VYCDGAIP*
    
por user300245 03.07.2014 / 21:53

1 resposta

7

Eu apresento aqui quatro soluções, duas usando sed , uma usando awk e uma usando perl . Para começar:

$ sed -r 's/^(>[^ ]+) .*//' inputfile

Em sua entrada de amostra, isso produz a saída:

>YAL001C
LTIYPDELVQIVSDKIASNKGKITLNQLWDISGKYFDLSDKKVKQFVLSCVILKKDIE
VYCDGAIP*

O código usa o comando substituto do sed s . O comando substituto está no formato s/old/new/ . Nesse caso, a parte "antiga" consiste nessas partes:

  • ^

    Isto é sed-speak para o início de uma linha.

  • (>[^ ]+)

    Refere-se a um grupo de caracteres que consiste em um colchete angular seguido por um ou mais caracteres não-brancos. Como isso está entre parênteses, poderemos nos referir a ele mais tarde como .

  • .*

    Isso se refere a um espaço em branco seguido por qualquer número de qualquer caractere.

Quando o comando substituto for concluído, toda a linha será substituída apenas pelos caracteres > e não em branco que a seguem imediatamente.

Qualquer linha que não comece com essa combinação será enviada para a saída inalterada.

Solução alternativa

Nos comentários, a steeldriver sugere uma abordagem alternativa:

sed '/^>/ s/\s.*//'

Nesta solução, o comando substituto é precedido pelo modificador /^>/ , que restringe o comando substituto a operar apenas nas linhas que começam com > . Sabendo que a linha começa com um colchete angular, então só é necessário remover o primeiro espaço em branco e tudo o que segue o primeiro espaço em branco. Isto é o que o comando s/\s.*// faz.

Todas as outras linhas são transmitidas inalteradas.

Solução alternativa usando awk

awk '/^>/ {print $1;next} 1' inputfile

Este script awk consiste em duas expressões:

  • /^>/ {print $1;next}

    awk suporta o mesmo estilo de modificadores que sed . A expressão inicial, portanto, restringe esse comando para operar apenas nas linhas que começam com > . Para essas linhas, o primeiro campo é impresso. next informa awk para pular para a próxima linha e começar de novo.

  • 1

    1 é awk de mãozinha enigmática para imprimir a linha inteira. Isso é executado apenas nas linhas para as quais o comando next na expressão anterior não é executado, o que significa que awk atinge este comando somente se a linha não iniciar com > .

Solução alternativa usando perl

a steeldriver também sugere:

perl -anle 'print $F[0] if /^>/ || $_'

As quatro opções têm o seguinte significado:

  • -n diz a perl para fazer um loop implicitamente nas linhas de entrada

  • -a diz ao perl para ativar o preenchimento automático, criando o @F array

  • -l ativa o processamento automático de finalização de linha

  • -e diz para executar o comando que segue, eliminando a necessidade de um arquivo de script perl.

O comando perl é bastante legível:

print $F[0] if /^>/ || $_

Este comando imprime o primeiro campo se a linha começar com > . Caso contrário, imprime toda a linha.

    
por John1024 03.07.2014 / 21:59

Tags