Categorias
Artigos Introdução à Programação para Bioinformática com Perl

“O guia de sobrevivência para expressões regulares em Perl”

Capítulo 8

Este conteúdo faz parte do livro “Introdução à Programação para Bioinformática com Perl“. Você pode adquirir a versão impressa desse livro aqui ou a versão para Kindle aqui. Para nos citar, consulte este link.

Uma das propriedades mais poderosas da linguagem Perl é a manipulação de strings. Aprendemos nos capítulos anteriores a fazer algumas tarefas básicas com strings, entretanto nada que se compare às robustas manipulações que podem ser feitas com expressões regulares. Neste capítulo apresentamos um “guia de sobrevivência” para uso de expressões regulares. Guia de sobrevivência é uma analogia ao fato de que expressões regulares podem facilitar a busca por padrões em arquivos de maneira simples, através de poucas linhas de código, o que em alguns casos pode até lhe “salvar de enrascadas”.

O que são expressões regulares?

Expressões regulares, regex ou ER, são técnicas para busca de padrões, extração ou substituição de cadeias de caracteres de forma concisa e flexível. Expressões regulares podem ser vistas como cadeias de caracteres que descrevem um padrão nos dados.

Nos capítulos anteriores, apresentamos algumas técnicas para comparação de strings, entretanto tais métodos apenas permitem comparações entre strings completas, sendo necessário o uso de métodos, como substr ou index, para burlar essas limitações e buscar por substrings.

Por exemplo, se utilizássemos expressão regular para buscar o padrão “tato” no conjunto de palavras (“alanina”, “cisteina”, “aspartato”, “glutamato”), obteríamos como resposta as palavras “aspartato” e “glutamato”, pois só elas possuem a substring “tato”.

Expressões regulares são um método avançado para análise de strings. Com expressões regulares é possível realizar buscas por substrings em curtas cadeias de caracteres a até mesmo grandes arquivos de texto.

As expressões regulares foram regulamentadas pela norma IEEE POSIX 1003.2 (POSIX.2) através de duas especificações: BRE (expressões regulares básicas) e ERE (expressões regulares estendidas). Tais normas visaram a padronização da sintaxe de expressões regulares, além disso ainda apresentou o uso dos metacaracteres (que serão individualmente descritos posteriormente).

Perl, entretanto, apresenta métodos mais robustos que as normas POSIX. Tanto é que outras linguagens, como JavaScript, Java, Ruby, Python, e até mesmo .NET adotaram sintaxes próximas a de Perl.

Introdução a busca por padrões em Perl

Perl permite o uso de expressões regulares para detecção de padrões através do operador “=~”. O operador “=~” requer que o padrão buscado seja indicado entre barras invertidas e retorna true (verdadeiro) caso o padrão seja encontrado. Observe:

my $frase = "Minha primeira busca por padroes usando Perl!";

if ($frase =~ /Perl/){
	print "Padrao 'Perl' encontrado na frase.\n";
}

if ($frase !~ /perl/){
	print "Padrao 'perl' nao encontrado na frase.\n";
}

Podemos ainda utilizar o operador de negação “!~” para verificar se o padrão indicado não está presente na variável analisada. A busca por padrões através dos operadores “=~” e “!~” é case sensitive, logo a string “Perl” é diferente da string “perl”.

Buscas por padrões em arquivos

Observe o exemplo a seguir. Nele utilizaremos mais uma vez o operador “=~” para fazer buscas em um arquivo. Para este exemplo utilizaremos o “arquivo4.txt” que pode ser baixado no diretório “exemplos” em <https://github.com/dcbmariano/perl>. O “arquivo4.txt” contém anotações do plasmídeo pREB9 do organismo Acaryochloris marina MBIC11017 e foi obtido no GenBank. Vamos fazer uma busca por linhas que apresentem nomes de produtos expressos por genes. Veja:

# Execute: perl c8_s2.pl arquivo4.txt 
use strict;

my $linha;

open (GBK, $ARGV[0]);

while($linha = <GBK>){

	if ($linha =~ /product=/){
		print $linha;
	}

}

#                     /product="hypothetical protein"
#                     /product="hypothetical protein"
#                     /product="hypothetical protein"
#                     /product="hypothetical protein"

Antes de iniciar uma busca generalizada através de um padrão de strings é necessário analisar manualmente o arquivo e detectar quais características definem esse padrão. Para o exemplo dado, procurávamos linhas com informações sobre nomes de produtos expressos por regiões codificadoras. Analisando o arquivo, detectamos que os nomes de produtos estavam indicados em “product=”. Com isso, percebemos que esse seria o padrão que deveríamos buscar.

Através de um laço de repetição analisamos cada linha em busca do padrão “product=” utilizando o operador “=~”.

if ($linha =~ /product=/){ # [...]

Nosso script detectou quatro linhas que apresentavam o padrão buscado.

Metacaracteres

Metacaracteres são um grupo símbolos que, individualmente ou quando combinados com outros, permitem a construção de expressões regulares mais complexas. Com metacaracteres é possível detalhar posições específicas para detecção de padrões de caracteres. Observe abaixo alguns metacaracteres.

. [ ] ? * + { } ^ $ \ | ( )

Os metacaracteres podem ser divididos em quatro grupos: representantes, âncoras, quantificadores e outros.

Metacaracteres representantes

Metacaracteres deste grupo permitem que elementos sejam associados.

Metacaractere NomeSignificado
.PontoBusca qualquer caractere simples (exceto /n).
[ ]ListaBusca por uma lista de caracteres indicados.
[^]Lista negadaBusca por uma lista de caracteres NÃO indicados na lista.

Agora vamos explorar os metacaracteres representantes. Nesse exemplo, vamos criar um array com sete elementos. Em seguida, vamos percorrer o array criado buscando itens que possuam os seguintes padrões:

(i) terminem com o caracter “i” seguido de qualquer ca-ractere e das três letras “ina”;

(ii) possuam dez caracteres ou mais e terminem com “ina”;

(iii) tenham o caractere A;

(iv) tenham os caracteres A, B, C, D, E ou F;

(v) tenham os caracteres A, B, C, D, E ou G;

(vi) sejam diferentes da string “Alanina”;

(vii) sejam diferentes da string “Cisteina” e “Glutamato”.

use strict;

my @lista = (
"Alanina","Cisteina","Aspartato","Glutamato",
"Fenilalanina","Glicina","Histidina"
);

my $l;

# Buscar palavras com as seguintes condicoes
foreach $l(@lista){

	######################## . ########################
	# Terminem com "ina" e antes 
	# tenha um caracter "i" seguido de qualquer outro
	if ($l =~ /i.ina/){
		print "i.na:\t$l\n"; # Glicina Histidina
	}

	# Tem 10 caracteres ou mais, e termina com "ina"
	if ($l =~ /.......ina/){
		print "...na:\t$l\n"; # Fenilalanina
	}

	######################## [] ########################
	# Tenha o caractere A
	if ($l =~ /[A e]/){
		print "[A e]:\t$l\n"; 
		# Alanina Aspartato Cisteina Fenilalanina
	}

	# Tenham alguns dos caracteres: A, B, C, D, E ou F 
	if ($l =~ /[A-F]/){
		print "[A-F]:\t$l\n"; 
		# Alanina Cisteina Aspartato Fenilalanina
	}

	# Tenham alguns dos caracteres: A, B, C, D, E ou G
	if ($l =~ /[A-E G]/){
		print "[A-EG]:\t$l\n"; 
		# Alanina Cisteina Aspartato Glutamato Glici-na
	}

	######################## [^] ########################
	# Todos diferentes de Alanina
	if ($l =~ /[^Alanina]/){
		print "[^Ala]:\t$l\n"; 
		# Cisteina, Aspartato, Glutamato, 
		# Fenilalanina, Glicina, Histidina
	}

	# Todos diferentes de Cisteina e Glutamato 
	if ($l =~ /[^Cisteina Glutamato]/){
		print "[^CG]:\t$l\n"; 
		# Alanina Aspartato Fenilalanina 
		# Glicina Histidina
	}

}

Pontos podem ser utilizados para representar quaisquer caracteres, entretanto a quantidade de pontos digitada força que a string buscada tenha pelo menos a mesma quantidade.

Dentro de uma lista, os elementos buscados são separados por um espaço. Para buscar um grupo sequencial de caracteres basta utilizar o caractere “-“. Por exemplo, para buscar os caracteres A, B, C, D e E pode-se utilizar o padrão: [A-E].

Metacaracteres Âncoras

Apresentam símbolos que permitem buscas no início e fim de linhas/strings.

MetacaractereNome Significado
^ CircunflexoBusca no início de uma linha/string.
$CifrãoBusca no início de uma linha/string.

Para o exemplo a seguir utilizaremos o arquivo PDB da proteína beta-glicosidase de Bacillus polymyxa (código 1BGA). Disponibilizamos uma cópia desse arquivo no repositório do GitHub “exemplos” com o título “arquivo5.txt”. Neste exemplo vamos buscar a linha do cabeçalho e, a seguir, linhas que representem átomos de enxofre.

O primeiro passo antes de iniciarmos o script é ler o arquivo e tentar entender qual padrão representa as duas informações que desejamos.

Primeiro, linhas de cabeçalho começam com a string “HEADER”, logo devemos buscar esse padrão no começo da linha. Segundo, linhas de átomos começam com a string “ATOM” e o tipo do átomo é definido no final da linha. O átomo de enxofre é representado pela letra “S”. É importante notar que após o caractere que define o átomo há dois espaços em branco. Observe como ficaria nosso script:

use strict;

my $linha;

open(PDB,"arquivo5.txt");

# Percorre arquivo
while($linha = <PDB>){

	# Linhas que comecem com header
	if($linha =~ /^HEADER/){
		print "Linha com string HEADER: ";
		print $linha;
	}

	# Linhas que comecem com ATOM e tenham um S no fim
	if(($linha =~ /^ATOM/) and ($linha =~ /S  $/)){
		print "Atomo S: ";
		print $linha;
	}

	# Voce pode usar o seguinte 
	# comando para detectar linhas vazias
	# if($linha =~ /^$/){
	#	[...]
	# }

}

Observe que se o símbolo ^ dentro de colchetes [ ] tem um significado diferente de fora. Dentro de colchetes indica que é uma lista negada, enquanto fora indica buscas no começo da linha.

Caso tenha interesse em buscar linhas vazias pode-se utilizar a expressão regular ^$.

Metacaracteres quantificadores

Os metacaracteres quantificadores indicam quantas vezes um determinado padrão de caracteres se repete. Os quantificadores são gulosos, ou seja, apresentam o primeiro resultado que atenda a uma requisição.

Metacaractere NomeSignificado
*AsteriscoPermite buscas por caracteres que aparecem várias vezes ou nenhuma vez.
?OpcionalPermite buscas por caracteres que não apareçam ou que apareçam uma única vez.
+MaisPermite buscas por caracteres que aparecem várias vezes ou pelo menos uma vez.
{z,y}ChavesPermite buscas por um caractere que apareça no mínimo x vezes e no máximo y vezes.

O metacaractere asterisco “” analisa se o caractere anterior ao símbolo aparece uma ou várias vezes, ou até mesmo não aparece. Por exemplo, “qwert” aceita os valores “qwet”, “qwert”, “qwerrt”, “qwerrrt”, e assim sucessivamente. Seu uso é ideal quando se sabe uma parte do texto buscado, mas essa parte pode apresentar variações.
O metacaractere opcional “?” analisa se o padrão buscado existe ou não. Ele é ideal para buscar, por exemplo, palavras no plural, uma vez que a diferença entre singular e plural muitas vezes é apenas uma letra “s”. No exemplo a seguir, buscaremos elementos que comecem com qualquer letra entre A e G, seguido obrigatori-amente de uma letra “l” e seguido ou não de um caractere “i”.
O metacaractere mais “+” analisa se o caractere anterior se repete várias vezes. Por exemplo, “baleia+” aceita “baleiaa”, “baleiaaa”, etc. Enquanto, os metacaracteres chaves “{mínimo, máximo}” indica o número mínimo e máximo de repetições do caractere anterior.
Observe agora o exemplo abaixo. Utilizamos metacaracteres quantificadores para analisar uma lista.

use strict;

# Metacaracteres quantitativos
my @lista = (
"Alanina","Cisteina","Aspartato","Glutamato",
"Fenilalanina","Glicina","Histidina"
);

my $l;

foreach $l(@lista){

  # * => analisa se o "u" aparece 0, 1 ou varias vezes
  if($l =~ /Glu*/){
    print "/Glu*/: $l \n"; # Glutamato Glicina
  }

  # ? => possui ou nao "i" apos o caractere "l"
  if($l =~ /[A-G]li?/){
    print "[A-G]li?: $l \n"; # Alanina Glutamato Glicina
  }

  # teste com + e {y,x}
  if($l eq "Histidina"){    
      
    # teste com 2 caracteres 'a'
    $l = "Histidinaa";

    if($l =~ /Histidina+/){
      print "Repeticao detectada na ultima letra.\n";
      # Repeticao detectada na ultima letra.
    }

    if($l =~ /Histidina{3,5}/){
      print "Exite entre 3 e 5 'a'.\n";
    }

    else{
      print "Numero de repeticoes menor que 3 ou maior que 5.\n";
    }

    # Numero de repeticoes menor que 3 ou maior que 5.
  }

}

Outros metacaracteres

Esta categoria agrupa metacaracteres com funções variadas.

MetacaractereNomeSignificado
|OuBusca pelo caractere à direita ou pelo caractere à esquerda.
( )AgrupamentoPermite a busca por grupos de caracteres.
\EscapeConverte metacaractere em um caractere normal.

Agora observe o exemplo a seguir:

use strict;

# Outros metacaracteres

my @lista = (
"Alanina","Cisteina","Aspartato","Glutamato",
"Fenilalanina","Glicina","Histidina"
);

foreach my $l(@lista){

	# Testando |
	if($l =~ /Alanina|Aspartato/){
		print "|: $l\n";
	}

	# Integrando | com ()
	if($l =~ /Gl(i|u)/){
		print "(|): $l\n";
	}

}
# |: Alanina
# |: Aspartato
# (|): Glutamato
# (|): Glicina

O metacaractere ou “|” indica que tanto uma condição quanto outra são válidas. O metacaractere de agrupamento “()” permite uma analise mais abrangente limitada por um grupo, e assim, dá mais poder aos outros metacaracteres. No exemplo demonstrado, integramos o metacaractere de agrupamento com o metacaractere “ou”, e assim buscamos palavras que se iniciem com “Gl” seguido de “u” ou “i”.

Metacaracteres perdem suas características quando indicados com uma barra invertida antes, como por exemplo: barra vertical \|, colchetes \[, parênteses /), asterisco \*, acento circunflexo \^, arroba \@, barra \/ e até mesmo a própria barra invertida \\.

Entretanto, há caracteres especiais que ganham características quando uma barra invertida os precede:

Caracteres controle
\nNova linha (LF ou NL).
\tTabulação
\rRetorno (CR).
\fForm feed (FF).
\eEscape (ESC).
\xCaractere com código hexadecimal representado por “hh”. Uso: \xhh.
\wCaractere alfa-numérico.
Equivalente a: [a-zA-Z_]
\WCaractere que não é alfa-numérico.
Equivalente a: [^a-zA-Z_]
\dDigito (numeral de 0-9).
Equivalente a: [0-9], [0123456789] ou (0|1|2|3|4|5|6|7|8|9)
\DNão digito.
Equivalente a: [^0-9].
\sQualquer espaçamento (espaço, tabulação, nova linha).
Equivalente a: [ ].
\SQualquer não espaço.
Equivalente a: [^ ].
\bLimite de palavra
\BCaractere que não está no limite de uma palavra

Os metacaracteres apresentados anteriormente quando combinados podem fornecer expressões regulares mais complexas.

Variáveis especiais em expressões regulares

Perl apresenta certas variáveis especiais que permitem acesso a padrões detectados em expressões regulares.

VariávelFunção
$<número>Permite acesso a padrões detectados entre parênteses. Tais informações ficam armazenadas nas variáveis $1, $2, $3 e assim por diante.
$&Armazena a string detectada pelo padrão.
$`Armazena a string anterior ao padrão detectado.
$’Armazena a string posterior ao padrão detectado.
$+Armazena a string detectada no último parêntese.

Busca e substituições  

Aprendemos anteriormente a utilizar buscas com o operador “=~”. Agora aprenderemos a realizar buscas e substituições de padrões de caracteres de uma nova forma. Para isso utilizamos a sintaxe:

s/string_buscada/string_substituição/modificador

Onde “s” indica search (busca) e requer entre duas barras “//” uma string a ser procurada, seguida, também entre duas “//”, por uma string que substituirá a anterior, além de um modificador, que poderá ser:

gSubstituição global. Modifica todos os elementos similares a string buscada. Por padrão, Perl substitui apenas o primeiro resultado.
iRealiza buscas case insensitive (não difere maiúsculas de minúsculas).
mRealiza buscas com strings de mais de uma linha.
sAvalia apenas strings com uma linha.
xDesconsidera espaços e comentários da avaliação.

No exemplo a seguir testaremos algumas técnicas de busca e substituição em uma frase a partir das declarações em Perl.

my $frase = "Expressões regulares, regex ou ER, 
são técnicas para busca de padrões, 
extração ou substituição de cadeias 
de caracteres de forma concisa e flexível.
";

# Substituicao simples
$frase =~ s/ER/expressões regulares/;
print "\n########### Substituicao simples ###########\n".$frase;

# Case sensitive
$frase =~ s/expressões regulares/ER/;
print "\n########### Case sensitive ###########\n".$frase;

# Primeiro elemento
$frase =~ s/,/!/;
print "\n########### Substituindo primeiro elemento ###########\n".$frase;

# Substituicao global
$frase =~ s/,/!/g;
print "\n########### Substituindo todos os elementos ###########\n".$frase;

# Case insensitive + global
$frase =~ s/ER/expressões regulares/; 

# Expressões regulares, regex ou expressões regulares, 
$frase =~ s/expressões regulares/ER/gi;
print "\n########### Case insensitive ###########\n".$frase;

Funções split e grep

Perl ainda fornece as funções split e grep, que complementam as expressões regulares. A função split recebe como entrada uma string seguida por um delimitador, e a quebra em um array. A função grep recebe um array e retorna elementos que estejam de acordo com um determinado conjunto.

No exemplo a seguir utilizaremos split para detectar o total de palavras em uma frase (utilizaremos o caractere especial “\s” para identificar espaços separadores) e grep para detectar elementos de um array terminados com a substring “ato”.

# Funcao Split

my $string = "Expressões regulares, regex ou ER, 
são técnicas para busca de padrões, extração ou 
substituição de cadeias de caracteres de forma 
concisa e flexível.";

my @palavras = split(/\s+/,$string);

my $numero_palavras = @palavras;

print "Detectamos um total de $numero_palavras palavras.\n";
# Detectamos um total de 23 palavras.


# Funcao grep

my @aminoacidos = (
"Alanina","Cisteina","Aspartato",
"Glutamato","Fenilalanina","Glicina","Histidina"
);

my @polares_negativo = grep(/ato$/,@aminoacidos);

print "polares_negativo: ";

print "@polares_negativo \n";
# polares_negativo: Aspartato Glutamato

Busca e substituição em arquivos por linha de comando

Perl permite o uso de comandos diretamente por linha de comando. Entretanto, neste livro optamos em utilizar scripts em todas as tarefas. Todavia, a busca e substituição de uma string, em certos casos, é uma tarefa simples que pode exigir apenas uma única linha de comando. Assim, consideramos fundamental aprender a executar buscas por padrões e substituições de strings via linha de comando.

No exemplo a seguir vamos alterar o “arquivo1.txt”. Abra o terminal (Linux/MacOS) ou CMD (Windows). Navegue até o diretório onde estão os arquivos e execute o comando:

perl -p -e “s/mundo/Perl/g arquivo1.txt” > novo_arquivo1.txt

O comando demonstrado permite que o “arquivo1.txt” seja percorrido, todas as ocorrências da palavra “mundo” sejam substituídas por “Perl” e o resultado seja impresso (-p) através de uma linha de comando (-e) e armazenado (>) no arquivo “novo_arquivo1.txt”.

Agora abra os dois arquivos e os compare. Tente também substituir todas as ocorrências da palavra “ATOM ” por “ÁTOMO” no “arquivo5.txt” e salve em um novo arquivo. Lembre-se que os arquivos PDB requerem uma quantidade exata de caracteres em uma linha. Logo, se quiser substituir uma palavra de quatro caracteres por uma de cinco caracteres, inclua um espaço após a primeira palavra para que o mesmo número de caracteres seja alterado e não cause problemas nos caracteres subsequentes.

Buscas avançadas em arquivos

Com os conhecimentos adquiridos até o momento acreditamos que você já consiga compreender como funcionam buscas avançadas em arquivos. A primeira tarefa que realizaremos será refazer o script que extrai o produto codificado pelas CDSs presente no “arquivo4.txt”. Observe:

# perl c8_s9.pl arquivo4.txt

open (GBK, $ARGV[0]);

while(my $linha = <GBK>){

	if ($linha =~ /product="(.*)"/){
		print "$1\n";
	}

}

#hypothetical protein
#hypothetical protein
#hypothetical protein
#hypothetical protein

No exemplo demonstrado, extraímos todos os caracteres (.*) presentes entre aspas duplas em linhas que contenham o seguinte padrão: /product=”(.*)”. O padrão detectado nas aspas é armazenado na variável $1. Se quiséssemos pegar a toda a string poderíamos utilizar a variável $&.

No próximo exemplo, além do nome do produto da CDS, vamos extrair o conteúdo do campo “translation”. O campo translation contém uma sequência de aminoácidos. Para entender melhor o que faremos precisamos analisar um trecho do arquivo que será analisado. Veja:

          /translation="MTALAGLKWQLASVYLK 
         GDECHPDYGHRKVWREGLEVVMKHP
         FTAISPRS"

O conteúdo que deve ser extraído está entre os trechos: /translation=” e “\n (aspas duplas seguidas de uma quebra de linha). Observe que há quatro análises que devem ser feitas:

(i)  linhas que possuem o padrão /translation=”sequência_de_aminoácidos”, ou seja, linhas que o resultado do campo translation só ocupe uma linha;

          /translation="MTALAGLKWQLASVYLK"

(ii) linhas que possuam /translation=”, mas cujo conteúdo continue em outras linhas;

          /translation="MTALAGLKWQLASVYLK

(iii) linhas que contenham uma sequência de aminoácidos, desde que se tenha detectado um campo translation anteriormente aberto, mas não fechado;

         GDECHPDYGHRKVWREGLEVVMKHP

(iv) linhas que contenham uma sequência de aminoácidos, desde que se tenha detectado um campo translation anteriormente aberto, não fechado, e que contenha as-pas duplas no final da linha, o que indica que a linha atual fecha o campo;

         FTAISPRS"

Uma informação importante que devemos levar em consideração sobre o campo translation é que seu conteúdo pode aparecer em mais de uma linha. Logo, precisaremos do apoio de uma variável auxiliar, que no nosso script será chamada de $mais_linhas. A variável $mais_linhas iniciará com o valor 0. Caso o script detecte que um determinado resultado possui mais de uma linha, nossa variável receberá o valor 1.

Antes de começarmos a desenvolver o script devemos definir os padrões de output. Os resultados deverão seguir o seguinte padrão: (i) uma CDS por linha; (ii) o nome do produto seguido por dois pontos e um espaço; e (iii) a sequência de aminoácidos. 

Agora, observe o script:

use strict;

# perl c8_s10.pl arquivo4.txt
open (GBK, $ARGV[0]);

# Variaveis auxiliares
my $mais_linhas = 0;
my $translation;

while(my $linha = <GBK>){

	# Extrai o nome do produto da CDS atual
	if ($linha =~ /product="(.*)"/){
		print "$1: ";
	}

	# Valida se o translation tem mais de uma linha
	if($mais_linhas == 1){

		if ($linha =~ /(.*)"/){
			$translation = $1;
			$translation =~ s/\s//g;
			print $translation."\n";
			# Nao ha mais linhas: 
			# zera a variavel mais_linhas
			$mais_linhas = 0;
		}

		elsif($linha =~ /\ (.*)\n/){
			$translation = $1;
			$translation =~ s/\s//g;
			print $translation;
		}

	}

	# resultado em 1 linha
	if ($linha =~ /translation="(.*)"/){
		print "$1\n";
	}

	#resultado em mais de uma linha
	elsif ($linha =~ /translation="(.*)/){
		$translation = $1;
		$translation =~ s/\s//g; 
# apaga espacos e quebras de linha
		print $translation;
		$mais_linhas = 1;
	}

}

# hypothetical protein: MHGCIFFTSNFSIKKLSLKQLFFGTLVKSLF
# TPVAETLIFNSFLKVVRIAAFSNQFYAAIRILFQSCQIQETSSSNQALVC
# hypothetical protein: MKKLVLLFFLSIAILAGSVTISHAQ-TFGPVFLVEYNTD
# RQGGDIRSGFPVGNVGQCMNECASSSQCRAFTFVDVNQQPPNYNNNRPL
# CWLKRSVPGKRRNSGMITGVRQ
# hypothetical protein: MTALAGLKDAQLFANGVYSAWEWVKACDGIR-WFTDGER
# RYGQELWQLASVYLKGDECHPDYGHRKVWREGLEVVMKVKGSQGNRRVEWVK
# TEHPFTAISPRSEIHANHNEAHNAALRRRCSAYRRRQNLYAKKRLGLQRVLD
# VQRLIHNWVRPHWGLSKQTTPAMEMGFCSRPLSTLELLTNKGFRYVPC
# hypothetical protein: MECPYCQSEKILKRGFDSLQDGTLVQRYQCK-DCNRR
# FNERTGTPMARLRTASSVVSYAIKARTEGMGVRSAGRTFGKSHTTIMRWEKRLAD
# QAQNWSPPRTSSL

Observe que inicialmente extraímos os nomes de produtos de CDSs. Em seguida, analisamos se a variável $mais_linhas é igual a 1. Essa validação deve aparecer no começo do script devido a ordem de leitura do arquivo. Não vamos explicar essa parte ainda. Em seguida analisamos se o conteúdo do campo translation está em uma única linha:

if ($linha =~ /translation=”(.*)”/){

Se o resultado da análise anterior for falso, analisamos se ele aparece em múltiplas linhas. Para isso basta verificar se não existem aspas duplas fechando o campo translation. Se essa condição for verdadeira, alteramos o valor da variável $mais_linhas para 1. Essa variável só será importante na próxima iteração. Voltemos ao início do código.

Se $mais_linhas for igual a 1, primeiro verificamos se há aspas duplas na linha. Se houver, indica que a linha atual fecha o campo, logo devemos remover quaisquer tipos de espaçamento usando uma variável temporária chamada $translation e aplicando uma técnica de substituição global que apaga espaços e quebras de linha ($translation =~ s/\s//g;) e, por fim, devemos imprimi-la. Alteramos também o valor da variável $mais_linhas para 0, a fim de impedir que esse bloco se repita na próxima linha (que não deverá conter nada relacionado ao campo translation). Se não houver aspas duplas, ou seja, a condição for falsa, verificamos se a linha atual se trata de uma linha central que contém apenas sequências de aminoácidos. Nesse caso, removemos os espaçamentos mais uma vez e a imprimimos.

Se tudo for executado como indicado obtemos como resultado os nomes de produtos de CDSs seguido das sequências de aminoácidos dos mesmos.

Como exercício, recomendamos que tente extrair outras informações do arquivo GenBank, como por exemplo, a posição das CDSs (campo misc_feature), a locus tag ou até mesmo tente extrair as sequências de nucleotídeos (apresentadas no fim do arquivo).

Quer aprender mais? Conheça nossos cursos profissionalizantes à partir de R$19,99:

Nota do autor
Prefácio

Capítulo 1
Introdução ao Perl

Capítulo 2
Comandos condicionais

Capítulo 3
Strings

Capítulo 4
Arrays

Capítulo 5
Laços de repetição

Capítulo 6
Manipulando arquivos

Capítulo 7
Sub-rotinas

Capítulo 8
“O guia de sobrevivência para expressões regulares em Perl”

Capítulo 9
Introdução ao BioPerl

Capítulo 10
Sequências

Capítulo 11
BLAST

Capítulo 12
Estruturas de proteínas

Capítulo 13
Hierarquia do BioPerl

Epílogo
Referências bibliográficas
Sobre os autores

Por favor, nos cite:

MARIANO, DIEGO CÉSAR BATISTA; de MELO-MINARDI, R. C. . Introdução à Programação para Bioinformática com Perl. 1. ed. North Charleston, SC (EUA): CreateSpace Independent Publishing Platform, 2016. v. 2. 200p .

Por Diego Mariano

Doutor em Bioinformática pela Universidade Federal de Minas Gerais com atuação na área de ciência de dados e aprendizado de máquina aplicados ao aperfeiçoamento de enzimas usadas na produção de biocombustíveis. Mestre em Bioinformática, também pela UFMG, atuando na área de desenvolvimento de sistemas Web para montagem de genomas. Atualmente realiza estágio pós-doutoral no Departamento de Ciência da Computação da UFMG com foco em desenvolvimento de sistemas Web para Bioinformática, análise exploratória e visualização de dados. Tem conhecimentos nas linguagens: PHP, JavaScript, Python, R, Perl, HTML, CSS e SQL.