2015-11-24 12 views
7

Chcę dopasować wszystko do określonego słowa (np. Zamykający komentarz w C */), jednak ze względów wydajnościowych nie chcę korzystać nie chciwych operatorów.Regex pasuje do wszystkiego - bez chciwych operatorów

Na przykład, aby dopasować komentarze C: /\*.*?\*/ jest zbyt wolny dla moich plików. Czy istnieje możliwość poprawy wydajności?

+0

Wydajność używania chciwego kontra nieautentycznego może zależeć od długości komentarza. –

Odpowiedz

7

Jasne, użyj unrolling-the-loop technique:

/\*[^*]*(?:\*(?!/)[^*]*)*\*/ 

Zobacz regex demo

rozwijając technikę pętli opiera się na założeniu, że w większości przypadków, to kown w repeteated naprzemiennie, co sprawa powinna być najbardziej typowy, a który wyjątkowy. Nazwiemy pierwszy, zwykły przypadek, a drugi specjalny przypadek. Ogólna składnia rozwijając technikę pętli można następnie zapisać jako:

normal* (special normal*)*

Co może oznacza coś, Match normalny przypadek, jeśli okaże się, szczególny przypadek, dopasowane, niż zgodne z normalną sprawę ponownie . Zauważysz, że część tej składni może potencjalnie prowadzić do superliniowego dopasowania. Aby uniknąć Neverending dopasowanie do dołączania, następujące zasady Powinni być ostrożnie stosowana:

  • początek szczególnym przypadku i normalnym przypadku muszą się wzajemnie wykluczać
  • specjalny zawsze musi dopasować co najmniej jeden znak
  • wyrażenie specjalne musi być atomowe: należy uważać na to, że (special normal*)* można zredukować do (special)*, co jeśli jest specjalne, to jest to special*, które stało się podobne do (a*)*, co jest wyrażeniem nieokreślonym.

deklaracja C# wzoru (przy użyciu dosłownie ciąg dosłowne):

var pattern = @"/\*[^*]*(?:\*(?!/)[^*]*)*\*/"; 

Podział regex:

  • /\* - dosłowne /*
  • [^*]* - 0 lub więcej znaków innych niż *
  • (?:\*(?!/)[^*]*)* - 0 lub więcej sekwencji ...
    • \*(?!/) - dosłowna * nie następuje /
    • [^*]* - 0 lub więcej znaków innych niż *
  • \*/ - dosłownym */

Tutaj jest wykres pokazujący jak skuteczny 3 potencjalnie identyczne regexps są (testowane pod regexhero.net *):

enter image description here

* Testowane przeciwko /* Comment * Typical * Comment */

+0

Cool. Nie wiedziałem o rozwijaniu pętli. Dzięki. +1 za to. –

+0

Dla "techniki rozwijania pętli" ... +1 – Stephan

+1

Dzięki za wspaniałą odpowiedź! –

1

Spróbuj tego:

/\*(?:[^*]|\*(?!/))*\*/

Nie wiem, czy to jest szybsza niż odpowiedzi stribizhev użytkownika.

+0

To wyrażenie '/ \ * (?: [^ *] | \ * [^ /]) * \ * /' Nie pasuje [ten komentarz] (https://regex101.com/r/lK9yE7/1) kończące się na '** /' ze względu na zanegowaną klasę znaków [^ /] 'po' '\ *' '. Tak więc, nawet jeśli jest to szybsze, jest po prostu inne w tym, co można dopasować. Jednakże wymaga znacznie więcej kroków, aby zwrócić poprawne dopasowanie niż wyrażenie regularne z powodu naprzemienności. –

+0

@stribizhev Rzeczywiście. Masz rację. Zmieniłem próbkę. –

+0

Dobrze, teraz są identyczne pod względem dopasowania, ale alternacja wciąż wymaga dużo więcej wycofywania w porównaniu z rozwiniętą wersją. –

Powiązane problemy