2012-05-16 16 views
6

Załóżmy, że chcę znaleźć w dużym (300 000 liter) wyrazie "psy" z odległością między literami dokładnie 40 000 liter pomiędzy. Więc robię:Perl: "Kwantyfikator {{}} większy niż 32766 w regex"

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

to będzie działać całkiem dobrze w innych językach (wolniej), ale w Perl rzuca mnie „kwantyfikator w {} większe niż 32766 w regex”.

Więc:

  1. możemy użyć większej liczby jako kwantyfikator jakoś?
  2. Jeśli nie, czy istnieje inny dobry sposób na znalezienie tego, czego chcę? Zauważ, że "psy" to tylko przykład; Chcę to zrobić dla dowolnego słowa i dowolnego rozmiaru skoku (i szybko).

Odpowiedz

9

Jeśli naprawdę trzeba to zrobić szybko chciałbym spojrzeć na poszukiwanie niestandardowych opartych na pomysłach Boyer-Moore string search. Wyrażenie regularne jest przetwarzane na skończoną maszynę stanu. Nawet sprytna, zwarta reprezentacja takiego FSM nie będzie bardzo skutecznym sposobem na wykonanie wyszukiwania, które opisujesz.

Jeśli naprawdę chcesz kontynuować, teraz możesz po prostu połączyć dwa wyrażenia, takie jak .{30000}.{10000}, które w praktyce są takie same jak .{40000}.

+0

Nicea obejście. Zastanawiałem się nad napisaniem czegoś od zera, ale jest to dla mnie trochę przesada, ponieważ w praktyce wyszukiwania, które przeprowadzę w metodzie regex brute-force, zajmie tylko dziesięć minut, co jest do przyjęcia dla moich zastosowań. –

+0

@GadiA Byłbym ciekawy, czy 'study' poprawi wydajność meczu. –

5

Myślę, że index może być lepiej dostosowane do tego zadania. Coś wzdłuż linii całkowicie niesprawdzone:

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

Łatwo zrobić powyższe mechanicznie, więc spełnia twoje żądanie "dowolnego rozmiaru". Po drugie, naprawdę chcesz użyć "s", inaczej/''/oznacza/'[^ \ n]'/będzie * dużo * niepotrzebnych kontroli. – ikegami