Esiste una scorciatoia Perl per contare il numero di corrispondenze in una stringa?

Supponiamo di avere:

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

Come dovrei giocare con il contesto per ottenere il numero di volte in cui il modello ha trovato una corrispondenza (3)? Questo può essere fatto usando un one-liner?

Ho provato questo:

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

Ho pensato che mettendo parentesi intorno al $number , avrei forzato il contesto dell’array, e con l’uso dello scalar avrei ottenuto il conteggio. Tuttavia, tutto ciò che ottengo è 1 .

Questo mette la regex stessa in un contesto scalare, che non è quello che vuoi. Invece, metti la regex nel contesto lista (per ottenere il numero di corrispondenze) e inseriscila in un contesto scalare.

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

Penso che il modo più chiaro per descriverlo sia evitare il cast istantaneo su scalare. Assegnare innanzitutto a un array e quindi utilizzare tale array in contesto scalare. Questo è fondamentalmente ciò che l’ = () = idioma farà, ma senza l’idioma (usato raramente):

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

Inoltre, vedi Perlfaq4 :

Esistono diversi modi, con una diversa efficienza. Se vuoi un conteggio di un certo singolo carattere (X) all’interno di una stringa, puoi usare la funzione tr /// in questo modo:

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

Questo va bene se stai cercando un singolo personaggio. Tuttavia, se stai cercando di contare più sottostringhe di caratteri all’interno di una stringa più grande, tr /// non funzionerà. Quello che puoi fare è racchiudere un ciclo while () attorno a un pattern match globale. Ad esempio, contiamo i numeri interi negativi:

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

Un’altra versione utilizza una corrispondenza globale nel contesto dell’elenco, quindi assegna il risultato a uno scalare, producendo un conteggio del numero di corrispondenze.

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

Prova questo:

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

Restituisce 3 per me. Creando un riferimento a un array, l’espressione regolare viene valutata nel contesto dell’elenco e @{..} rimanda il riferimento dell’array.

Il seguente codice è un one-liner?

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

un altro modo,

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

controllato con Benchmark, è piuttosto veloce

Il metodo di Friedo è: $a = () = $b =~ $c .

Ma è ansible semplificare ulteriormente anche solo a ($a) = $b =~ $c , in questo modo:

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

Si potrebbe ringraziare solo concludere questo in una funzione, getMatchCount() , e non preoccuparsi di distruggere la stringa passata.

D’altra parte, è ansible aggiungere uno swap, che può essere un po ‘più di calcolo, ma non comporta alterare la stringa.

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