2012-05-16 11 views
6

Digamos que quiero encontrar en un gran (300,000 letras) la palabra "perros" con la distancia entre letras exactamente 40,000 letras en el medio. Así que hago:Perl: "Cuantificador en {,} más grande que 32766 en expresiones regulares"

$mystring =~ m/d.{40000}o.{40000}g.{40000}s/; 

Esto funciona bastante bien en otros idiomas (más lento) pero en Perl que me tira "cuantificador en {,} mayor que 32766 en expresiones regulares".

Así:

  1. ¿Se puede utilizar un número más grande como el cuantificador de alguna manera?
  2. Si no, ¿hay otra buena manera de encontrar lo que quiero? Tenga en cuenta que "perros" es solo un ejemplo; Quiero hacer esto para cualquier palabra y cualquier tamaño de salto (y rápido).

Respuesta

9

Si realmente necesita hacer esto rápido Me gustaría ver una búsqueda personalizada en base a las ideas de Boyer-Moore string search. Una expresión regular se analiza en una máquina de estados finitos. Incluso una representación inteligente y compacta de dicho FSM no será una forma muy efectiva de ejecutar una búsqueda como usted describe.

Si realmente desea continuar a lo largo de las líneas que está ahora puede simplemente concatenar dos expresiones como .{30000}.{10000} que es lo mismo que .{40000} en la práctica.

+0

Niza solución alternativa. Consideré escribir algo desde cero, pero es un poco exagerado para mí, ya que en la práctica las búsquedas que ejecutaré en el método de expresión bruta de fuerza bruta tomarán solo diez minutos más o menos, lo cual es aceptable para mis usos. –

+0

@GadiA Me gustaría saber si 'study' mejoraría el rendimiento del partido. –

5

Creo que index podría ser más adecuado para esta tarea. Algo a lo largo de las líneas de la, no está comprobado:

sub has_dogs { 
    my $str = shift; 
    my $start = 0 

    while (-1 < (my $pos = index $$str, 'd', $start)) { 
     no warnings 'uninitialized'; 
     if (('o' eq substr($$str, $pos + 40_000, 1)) and 
      ('g' eq substr($$str, $pos + 80_000, 1)) and 
      ('s' eq substr($$str, $pos + 120_000, 1))) { 
      return 1; 
     } 
    } 
    return; 
} 
5

40.000 = 2 * 20.000

/d(?:.{20000}){2}o(?:.{20000}){2}g(?:.{20000}){2}s/s 
+0

Es fácil hacer lo anterior mecánicamente, por lo que satisface su solicitud de "cualquier tamaño". En segundo lugar, realmente desea usar "s", de lo contrario /' ./ significa/'[^ \ n]'/sería * mucho * de comprobaciones innecesarias. – ikegami

Cuestiones relacionadas