2013-09-24 10 views
6

Dzisiaj natknąłem się na następujący wyrażenia regularnego i chciał wiedzieć, co Ruby zrobi z nim:sens `+` następstwie `*`, gdy ten ostatni jest stosowany jako kwantyfikator w wyrażeniu regularnym

> "#a" =~ /^[\W].*+$/ 
=> 0 
> "1a" =~ /^[\W].*+$/ 
=> nil 

W tym przypadku Ruby wydaje się ignorować znak +. Jeśli to nie jest poprawne, nie jestem pewien, co z tym robi. Zgaduję, że nie jest interpretowany jako kwantyfikator, ponieważ * nie jest escaped i jest używany jako kwantyfikator. W wyrażeń regularnych w języku Perl/Ruby, czasami gdy znak (np. -) jest używany w kontekście, w którym nie można go interpretować jako znaku specjalnego, jest traktowany jako literał. Ale jeśli tak się dzieje w tym przypadku, spodziewam się, że pierwszy mecz się nie powiedzie, ponieważ w ciągu lwartości nie ma wartości +.

Czy to jest subtelnie poprawne użycie znaku +? Czy powyższe zachowanie jest błędem? Czy brakuje mi czegoś oczywistego?

+0

Skąd się wziął ten regex? –

+0

W niektórych materiałach bezpieczeństwa stron trzecich napotkanych w trakcie mojej pracy. Zgaduję, że regex nie jest zgodny z zamierzeniami autora, ale kiedy zobaczyłem zachowanie Ruby, zacząłem mieć pytania dotyczące tego założenia. –

Odpowiedz

5

Cóż, z pewnością można użyć + po *. Możesz przeczytać trochę o tym on this site. Obiekt + po * nazywany jest kwantyfikatorem dzierżawczym.

Co robi? Zapobiega to cofnięciu się *.

Zwykle, gdy masz coś podobnego .*c i za pomocą tego dopasować abcde The .* najpierw dopasować cały ciąg (abcde) i od regex nie może się równać c po .*, silnik będzie wrócić po jednym znaku czas, aby sprawdzić, czy jest dopasowanie (to jest wycofanie).

Po cofnięciu do c otrzymasz od mecz z abcde.

Teraz wyobraź sobie, że silnik musi wracać kilkaset znaków, a jeśli masz zagnieżdżone grupy i stwardnienie * (lub + lub forma {m,n}), można szybko skończyć z tysięcy, miliony znaków prezydentom, o nazwie catastrophic backtracking.

W tym miejscu przydatne są kwantyfikatory dzierżawcze. W rzeczywistości uniemożliwiają one jakąkolwiek formę cofania. W powyższym wyliczeniu, o którym wspomniałem, abcde nie zostanie dopasowane przez .*+c. Gdy .*+ zużyje cały ciąg, nie może się wycofać, a ponieważ na końcu ciągu nie ma c, dopasowanie nie powiedzie się.

Innym możliwym sposobem wykorzystania kwantyzatorów ilościowych jest to, że mogą poprawić wydajność niektórych wyrażeń regularnych, o ile silnik może je obsługiwać.

Dla twojego regex /^[\W].*+$/, nie sądzę, że jest jakaś poprawa (może niewielka poprawa), którą zapewnia kwantyzator dzierżawczy. I na koniec można go z łatwością przepisać jako /^\W.*+$/.

+0

Jedyne ulepszenie, jakie możesz uzyskać, to to, że silnik nie musi zapisywać stanów pośrednich, a jednocześnie pasuje do '. *' (Które * będzie * używane do późniejszego śledzenia).Ale wzór nigdy się nie wycofa, więc nie ma oszczędności na tym końcu. –

+0

Doskonały napis - dziękuję. –

+0

@EricWalker Nie ma za co :) – Jerry

Powiązane problemy