Eu gostaria de usar o grep para copiar de um arquivo para outro todas as linhas que estão entre linhas /protein_id=
até o final da sequência de proteínas mostrada. Por exemplo, a partir desta entrada:
CDS 448..1269
/gene="nptII"
/note="neomycin phosphotransferase II"
/codon_start=1
/product="kanamycin resistance protein"
/protein_id="AAQ05967.1"
/db_xref="GI:33320494"
/translation="MAITLSATSLPISARIRAGSPAAWVERLFGYDWAQQTIGCSDAA
VFRLSAQGRPVLFVKTDLSGALNELQDEAARLSWLATTGVPCAAVLDVVTEAGRDWLL
LGEVPGQDLLSSHLAPAEKVSIMADAMRRLHTLDPATCPFDHQAKHRIERARTRMEAG
LVDQDDLDEEHQGLAPAELFARLKARMPDGEDLVVTHGDACLPNIMVENGRFSGFIDC
GRLGVADRYQDIALATRDIAEELGGEWADRFLVLYGIAAPDSQRIAFYRLLDEFF"
regulatory 1443..2148
Eu gostaria desta saída:
/protein_id="AAQ05967.1"
/db_xref="GI:33320494"
/translation="MAITLSATSLPISARIRAGSPAAWVERLFGYDWAQQTIGCSDAA
VFRLSAQGRPVLFVKTDLSGALNELQDEAARLSWLATTGVPCAAVLDVVTEAGRDWLL
LGEVPGQDLLSSHLAPAEKVSIMADAMRRLHTLDPATCPFDHQAKHRIERARTRMEAG
LVDQDDLDEEHQGLAPAELFARLKARMPDGEDLVVTHGDACLPNIMVENGRFSGFIDC
GRLGVADRYQDIALATRDIAEELGGEWADRFLVLYGIAAPDSQRIAFYRLLDEFF"
Observe que a entrada pode variar, pois a linha que começa com regulatory
pode ser substituída por outra coisa. O que não muda é que a sequência é dada em letras maiúsculas e termina com a "
. É possível com grep?
Responder1
pcregrep
é um utilitário grep que usa expressões regulares compatíveis com Perl 5. Os regexps no estilo Perl têm muitos recursos úteis que os POSIX padrão não possuem. É basicamente o mesmo que grep, mas com uma sintaxe regexp diferente.
sudo apt-get install pcregrep
pcregrep -M .*'/protein_id=.*(\n|.)*\"' path/to/input-file
/protein_id
é o termo de pesquisa inicial e "
é o termo de pesquisa final.
Aqui está um exemplo generalizado de um comando para fazer uma pesquisa multilinha para todas as linhas que estão entre um termo de pesquisa inicial e um termo de pesquisa final:
pcregrep -M .*'START-SEARCH-TERM.*(\n|.)*END-SEARCH-TERM' path/to/SOURCE-FILE >> path/to/DESTINATION-FILE
onde:
- SOURCE-FILE é o arquivo que contém seus dados
- DESTINATION-FILE é o arquivo onde os resultados serão copiados
- START-SEARCH-TERM é o termo de pesquisa inicial
- END-SEARCH-TERM é o termo de pesquisa final
-M, --multiline
Permita que os padrões correspondam a mais de uma linha.
Responder2
Não, grep
não é possível combinar várias linhas. Você poderia fazer isso pcregrep
como mostrado por @karel, mas não puro grep
. Em vez disso, como você sabe que as sequências de proteínas estarão sempre em MAIÚSCULAS e terminarão com "
, você pode combinar isso:
sed
sed -n '/\/protein_id=/,/^\s*[[:upper:]]\+"\s*$/{p}' two_seq.txt
O
sed
padrão/foo/,/bar/{p}
significa "imprimir todas as linhas entrefoo
ebar
.-n
Suprime a saída normal para que apenas as linhas solicitadas sejam impressas. Observe que/
of/protein_id=
precisa ser escapado (\/
) porque/
faz parte do operador de correspondência. O segundo padrão é um pouco mais complexo, procura 0 ou mais espaços no início da linha (^\s*
), depois uma ou mais letras maiúsculas seguidas de aspas duplas ([[:upper:]]"
) e depois 0 ou mais caracteres de espaço em branco até o final da linha (\s*$
).Perl
perl -ne 'print if m#/protein_id=# ... m#[A-Z]+"\s*$#' file.flat
A mesma ideia aqui, o
...
operador especifica um intervalo e as linhas entre os dois padrões são impressas.awk
awk '/\/protein_id=/{a=1}; a==1{print} /^\s*[[:upper:]]+"\s*$/{a=0}' file.flat
Aqui, estamos definindo a variável
a
para1
se a linha corresponder ao primeiro padrão e0
se corresponder ao último. Então, dizemosawk
para imprimir ifa
is1
. Como oprint
é chamado antesa
de ser definido como0
para o segundo padrão, isso incluirá também a linha que contém o segundo padrão.