2013-07-29 14 views
5

Po prostu zrobiłem zabawne krzyżówki z wyrażeniami w http://regexcrossword.com/ - i odkryłem, że nie rozumiem, co oznaczają grupy oznaczające, np. (.) (.) + Lub *Regex, grupa i quantifyer

Pozwól mi spróbować na http://ole.michelsen.dk/tools/regex.html, oferuje silnik JavaScript i PHP regex: "Trololo"

Ciąg dopasować przeciwko jest (bez cudzysłowów). (Jeśli włączeniu „Global meczu” coś zmieniło, jest ona dodawana jako wersja zagruntowane, czyli JS”, ​​jak to nic nie zmieni w trybie PHP).

JS, (.)+ => 0: Trololo! 1: ! 
JS', (.)+ => 0: Trololo! 
PHP, (.)+ => 0: Trololo! 0: ! 
JS, (.)* => 0: Trololo! 1: ! 
JS', (.)* => 0: Trololo! 
PHP, (.)* => 0: Trololo! 1: 0: ! 1: 
JS, (.){5} => 0: Trolo 1: o 
JS', (.){5} => 0: Trolo 
PHP, (.){5} => 0: Trolo 0: o 
JS, (.){4} => 0: Trol 1: l 
JS', (.){4} => 0: Trol 1: olo! 
PHP, (.){4} => 0: Trol 1: olo! 0: l 1: ! 

Czy jest jakaś odpowiedź normatywna co się semantyka tego jest?

+0

Co to są 'JS' i' JS''? Co za różnica? –

+1

Uważam, że ta strona nie podaje właściwych grup. Zamiast tego użyj http://www.regexplanet.com/. –

Odpowiedz

3

Wyjścia nie są poprawnie opisane, to wszystko.

Po pierwsze, co powinno być powinno być? Jeśli powtórzysz grupę, każda nowa instancja zastąpi ostatnie przechwycenie. Jeśli grupa nie jest w ogóle używana, zwróci pusty ciąg znaków lub coś w rodzaju JS (zależnie od smaku). Istnieje dobry artykuł na temat regular-expressions.info w tej sprawie.

Teraz, jak możemy osiągnąć twoje wyniki? Zacznijmy od JavaScript.

Wszystkie przykłady oznaczone jako JS (inne niż globalne) pasują do powyższego opisu. Pasują do żądanej liczby znaków w 0 i przechwytują ostatni znak w 1. Możemy to zignorować.

Co jest z tymi globalnymi? Tutaj wynik został nieprawidłowo zinterpretowany. Kiedy używasz globalnej flagi z funkcją String.match(), nie dostajesz już tablicy wszystkich przechwytujących - ale tylko tablicę wszystkich dopasowań (grupa 0 dla każdego dopasowania). Stąd w przypadku +, * i {5}, gdzie jest tylko jeden mecz, otrzymujesz tylko jeden wynik. Przy {4} jest wystarczająco dużo miejsca na dwa dopasowania w ciągu docelowym, więc wynikowa tablica zawiera dwa elementy. Aby uzyskać wszystkie przechwyty z flagą globalną, musisz napisać pętlę i użyć zamiast niej wartości RegExp.exec() (co daje jeden dopasowany obraz na raz, ale wszystkie jego przechwycenia).

A co z PHP? Wygląda na to, że używa on preg_match_all, która jest globalna i dlatego użycie g nie przyniosło żadnego efektu. Model + daje oczekiwany rezultat. Tak samo jest z {5}.

Co z pozostałymi dwoma? Tutaj wynik został zinterpretowany w niewłaściwy sposób. Domyślnie preg_match_all podaje tablicę dwuwymiarową, gdzie pierwszy indeks odpowiada grupie, a drugi odpowiada dopasowaniu. W twoim wyjściu jest interpretowany odwrotnie. W związku z tym, gdy występuje wiele dopasowań, pierwsza para 0 i jest zgodna z dwoma znalezionymi dopasowaniami. Druga para to te, które przechwyciłeś w tych dwóch meczach.

Tak więc dla * najpierw otrzymuje się pełny ciąg jako dopasowanie, a ostatni znak jako przechwytywanie (dwie rzeczy oznaczone jako 0), co jest poprawne. A ponieważ od * dopuszcza dopasowania o zerowej szerokości, otrzymasz inny (pusty) mecz na końcu ciągu wraz z pustym przechwytywaniem.Nie jestem pewien, dlaczego odpowiedni przykład JS' nie zawiera dodatkowego pustego łańcucha, ponieważ String.match zrobiłby to samo.

I {4}, po prostu dostać dwa mecze (Trol i olo!) jak w przypadku JavaScript z przechwyconych l i !, odpowiednio, co jest znowu perfekcyjnie.

+0

> Po pierwsze, co powinno się stać? Dokładnie, to jest pytanie :-) Rzeczywiście oczekiwałem, że dopasowanie (.) * Na abcd da 0. abcd 1. a 2. b 3. c 4. d - to znaczy, że dostaję więcej grup, ponieważ kwantyfikator wydaje się kwantyfikować grupę. Ale myślenie o tym dłużej, nie wydaje się w ogóle możliwe, ponieważ odniesienia do grupy są poprawione. – Falko

+1

@Falko, jedyny smak regex, który to robi .NET. Nie ma obiektu grupy dla każdej grupy, która zawiera zbiór przechwytywania. –

+0

Ah, fajnie. Ale jak już wspomniano, nie wyobrażam sobie, jak może to być przydatne w praktyce. – Falko