Contando el número de ocurrencias de una cadena dentro de otra (Perl)

¿Cuál es la forma más rápida de contar la cantidad de veces que aparece una cuerda determinada en una más grande? Mi mejor opción sería reemplazar todas las instancias de esa cadena con nada, calcular la diferencia de longitudes y dividir por la longitud de la subcadena, pero parece bastante lento, y necesito analizar grandes cantidades de datos.

Puedes capturar las cuerdas y luego contarlas. Se puede hacer aplicando un contexto de lista a la captura con () :

 my $x = "foo"; my $y = "foo foo foo bar"; my $c = () = $y =~ /$x/g; # $c is now 3 

También puede capturar una matriz y contar la matriz. Mismo principio, técnica diferente:

 my @c = $y =~ /$x/g; my $count = @c; 
 my $string = "aaaabbabbba"; my @count = ($string =~ /a/g); print @count . "\n"; 

o

 my $count = ($string =~ s/a/a/g); 

Podría usar una expresión regular global. Algo como:

 my @matches = $bigstring =~ /($littlestring)/g; my $count = @matches; 

Solo para completar, puede llamar repetidamente a la función de índice en un bucle y contar todas las veces que devolvió el índice de la subcadena en la cadena y cambiar la posición de inicio. Eso evitaría el uso de expresiones regulares, y en mis pruebas es un poco más rápido que las soluciones de expresiones regulares.

He adaptado un sub para hacer eso desde aquí: http://www.misc-perl-info.com/perl-index.html

 sub occurrences { my( $x, $y ) = @_; my $pos = 0; my $matches = 0; while (1) { $pos = index($y, $x, $pos); last if($pos < 0); $matches++; $pos++; } return $matches; }