web-dev-qa-db-fra.com

Existe-t-il un raccourci Perl pour compter le nombre de correspondances dans une chaîne?

Supposons que j'ai:

my $string = "one.two.three.four";

Comment dois-je jouer avec le contexte pour obtenir le nombre de fois où le motif a trouvé une correspondance (3)? Cela peut-il être fait en utilisant une doublure?

J'ai essayé ceci:

my ($number) = scalar($string=~/\./gi);

Je pensais qu'en mettant des parenthèses autour de $number, Je forcerais le contexte du tableau, et en utilisant scalar, j'obtiendrais le nombre. Cependant, tout ce que je reçois est 1.

74
Geo

Cela met le regex lui-même dans un contexte scalaire, ce qui n'est pas ce que vous voulez. Au lieu de cela, placez l'expression régulière dans le contexte de la liste (pour obtenir le nombre de correspondances) et placez que dans le contexte scalaire.

 my $number = () = $string =~ /\./gi;
112
friedo

Je pense que la façon la plus claire de décrire cela serait d'éviter la conversion instantanée en scalaire. Attribuez d'abord à un tableau, puis utilisez ce tableau dans un contexte scalaire. C'est essentiellement ce que fera l'idiome = () =, mais sans l'idiome (rarement utilisé):

my $string = "one.two.three.four";
my @count = $string =~ /\./g;
print scalar @count;
32
Robert P

Voir aussi Perlfaq4 :

Il existe plusieurs façons, avec une efficacité variable. Si vous voulez compter un certain caractère unique (X) dans une chaîne, vous pouvez utiliser la fonction tr /// comme ceci:

$string = "ThisXlineXhasXsomeXx'sXinXit";
$count = ($string =~ tr/X//);
print "There are $count X characters in the string";

C'est très bien si vous cherchez juste un seul personnage. Cependant, si vous essayez de compter plusieurs sous-chaînes de caractères dans une chaîne plus grande, tr /// ne fonctionnera pas. Ce que vous pouvez faire, c'est boucler une boucle while () autour d'une correspondance de modèle global. Par exemple, comptons les entiers négatifs:

$string = "-9 55 48 -2 23 -76 4 14 -44";
while ($string =~ /-\d+/g) { $count++ }
print "There are $count negative numbers in the string";

Une autre version utilise une correspondance globale dans le contexte de la liste, puis attribue le résultat à un scalaire, produisant un décompte du nombre de correspondances.

$count = () = $string =~ /-\d+/g;
20
Robert P

Le code suivant est-il une ligne?

print $string =~ s/\./\./g;
7
Mike

Essaye ça:


my $string = "one.two.three.four";
my ($number) = scalar( @{[ $string=~/\./gi ]} );

Il renvoie 3 pour moi. En créant une référence à un tableau, l'expression régulière est évaluée dans le contexte de la liste et le @{..} supprime la référence du tableau.

6
PP.

J'ai remarqué que si vous avez une condition OR dans votre expression régulière (par exemple /(K..K)|(V.AK)/gi) alors le tableau produit peut avoir des éléments non définis qui sont inclus dans le compte à la fin.

Par exemple:

my $seq = "TSYCSKSNKRCRRKYGDDDDWWRSQYTTYCSCYTGKSGKTKGGDSCDAYYEAYGKSGKTKGGRNNR";
my $regex = '(K..K)|(V.AK)';
my $count = () = $seq =~ /$regex/gi;
print "$count\n";

Donne une valeur de compte de 6.

J'ai trouvé la solution dans ce post Comment puis-je supprimer tous les undefs du tableau?

my $seq = "TSYCSKSNKRCRRKYGDDDDWWRSQYTTYCSCYTGKSGKTKGGDSCDAYYEAYGKSGKTKGGRNNR";
my $regex = '(K..K)|(V.AK)';
my @count = $seq =~ /$regex/gi;
@count = grep defined, @count; 
my $count = scalar @count;
print "$count\n";

Ce qui donne alors la bonne réponse de trois.

0