Tenho um código muito simples que analisa um nome de arquivo:
#!/usr/bin/env perl
use 5.040;
use warnings FATAL => 'all';
use autodie ':default';
my $string = '/home/con/bio.data/blastdb/phytophthora.infestans.KR_2_A2/GCA_012552325.1.protein.faa';
if ($string =~ m/blastdb\/(\w)\w+\.([\w\.]+)/) {
my $rest = $2; # $1 would be valid here
$rest =~ s/\./ /g;
my $name = "$1.$rest"; # $1 disappears here
}
o código acima falha comUse of uninitialized value $1 in concatenation (.) or string
Porém, se eu salvar $1
em uma variável, por exemplo $g
, a informação não será perdida.
if ($string =~ m/blastdb\/(\w)\w+\.([\w\.]+)/) {
my ($g, $rest) = ($1, $2);
$rest =~ s/\./ /g;
my $name = "$g.$rest";
}
Então eu posso consertar isso.
No entanto, $1
não deveria simplesmente desaparecer assim, não deveria $1
permanecer válido enquanto estiver no escopo? Isso é um bug no Perl? ou há alguma regra em https://perldoc.perl.org/perlretut que eu perdi?
$rest =~ s/\./ /g;
faz uma correspondência de regex. O padrão ao qual corresponde (/\./
) não possui nenhum grupo de captura, portanto, todas as variáveis de captura não são inicializadas após sua conclusão.Você pode salvar o que precisa em variáveis - mais simplesmente, fazendo
if (my ($g, $rest) = $string =~ /yadda yadda/)
ou pode evitar fazer outras correspondências de regex antes de terminar as capturas da anterior - neste caso,$rest =~ tr/./ /
faria o trabalho tão bem quanto$rest =~ s/\./ /g
, mas sem derrotando as variáveis de captura.