web-dev-qa-db-fra.com

Avertissement Perl: Utilisation de la valeur non initialisée dans la concaténation (.) Ou la chaîne

Je ne peux pas comprendre pourquoi les motifs de regex ne correspondent pas. De plus, la sortie se plaint que $found n'est pas initialisé, mais je crois l'avoir fait. Voici mon code jusqu'à présent:

use strict;
use warnings;

my @strange_list = ('hungry_elephant', 'dancing_dinosaur');

my $regex_patterns = qr/
    elephant$
    ^dancing
    /x;

foreach my $item (@strange_list) {
    my ($found) = $item =~ m/($regex_patterns)/i;
    print "Found: $found\n";
}

Voici la sortie que je reçois:

Use of uninitialized value $found in concatenation (.) or string at C:\scripts\Perl\sandbox\regex.pl line 13.
Found:
Use of uninitialized value $found in concatenation (.) or string at C:\scripts\Perl\sandbox\regex.pl line 13.
Found:

Dois-je initialiser $found d'une autre manière? De plus, est-ce que je crée correctement une chaîne multiligne à interpréter comme regex?

Merci beaucoup.

13
Dirty Penguin

Si le motif correspondant (=~) ne correspond à rien, rien ne sera stocké dans votre scalaire $found, aussi Perl se plaint que vous essayez d'interpoler une variable à laquelle aucune valeur n'a été donnée. 

Vous pouvez contourner cela facilement en utilisant postfix sauf si c'est conditionnel:

$found = "Nothing" unless $found
print "Found: $found\n";

Le code ci-dessus attribue la valeur "Nothing" à $found uniquement s'il n'a pas déjà de valeur. Désormais, votre relevé d’impression fonctionnera toujours correctement, dans les deux cas. 

Vous pouvez également simplement utiliser une simple instruction if, mais cela semble plus détaillé:

if( $found ) {
   print "Found: $found\n";
}
else {
   print "Not found\n";
}

Une autre option qui pourrait être la plus propre consiste à placer votre correspondance de modèle dans l'instruction if:

if( my ($found) = $item =~ m/($regex_patterns)/i ) {
   # if here, you know for sure that there was a match
   print "Found: $found\n";
}
17
Hunter McMillen

Votre expression régulière manque un séparateur. Insérez | entre l'éléphant et la danse.

De plus, vous devriez imprimer Found uniquement si quelque chose a vraiment été trouvé. Vous pouvez résoudre ce problème en

print "Found: $found\n" if defined $found;
2
choroba

La double barre oblique (//) peut également être utilisée pour initialiser $found. Il ressemble beaucoup à unless. La seule chose à faire est de modifier la ligne print comme suit.

print "Found: " . ($found // 'Nothing') . "\n";

Si $found n'est pas initialisé, 'Rien' sera imprimé.

Le résultat (Perl v5.10.1):

Found: Nothing
Found: Nothing
0
ahmedus