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

Supposons que j’ai:

my $ssortingng = "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)? Est-ce que cela peut être fait en utilisant une seule doublure?

J’ai essayé ceci:

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

Je pensais qu’en mettant des parenthèses autour de $number , je forcerais le contexte du tableau, et en utilisant un scalar , j’obtiendrais le compte. Cependant, tout ce que j’obtiens est 1 .

Cela place le regex lui-même dans un contexte scalaire, ce qui n’est pas ce que vous voulez. Au lieu de cela, placez le regex dans le contexte de la liste (pour obtenir le nombre de correspondances) et placez -le dans le contexte scalaire.

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

Je pense que la manière la plus claire de décrire cela serait d’éviter le passage instantané au scalaire. Affectez d’abord à un tableau, puis utilisez ce tableau dans un contexte scalaire. C’est fondamentalement ce que fera le = () = idiome, mais sans l’idiome (rarement utilisé):

 my $ssortingng = "one.two.three.four"; my @count = $ssortingng =~ /\./g; print scalar @count; 

Voir aussi Perlfaq4 :

Il y a un certain nombre de manières, avec une efficacité variable. Si vous voulez un compte d’un certain caractère unique (X) dans une chaîne, vous pouvez utiliser la fonction tr /// comme suit:

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

C’est 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 est d’envelopper une boucle while () autour d’une correspondance de motif globale. Par exemple, comptons les entiers négatifs:

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

Une autre version utilise une correspondance globale dans un contexte de liste, puis atsortingbue le résultat à un scalaire, ce qui génère un décompte du nombre de correspondances.

 $count = () = $ssortingng =~ /-\d+/g; 

Essaye ça:

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

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

Le code suivant est-il un one-liner?

 print $ssortingng =~ s/\./\./g; 

autrement,

 my $ssortingng = "one.two.three.four"; @s = split /\./,$ssortingng; print scalar @s - 1; 
 my $count = 0; my $pos = -1; while (($pos = index($ssortingng, $match, $pos+1)) > -1) { $count++; } 

vérifié avec Benchmark, c’est assez rapide

La méthode de Friedo est: $a = () = $b =~ $c .

Mais il est possible de simplifier cela encore plus loin pour juste ($a) = $b =~ $c , comme ceci:

 my ($matchcount) = $text =~ s/$findregex/ /gi; 

Vous pouvez remercier juste envelopper ceci dans une fonction, getMatchCount() , et ne pas vous soucier de détruire la chaîne passée.

D’un autre côté, vous pouvez append un swap, ce qui peut être un peu plus complexe, mais ne modifie pas la chaîne.

 my ($matchcount) = $text =~ s/($findregex)/$1/gi;