(Non)Greedy Quantification

Znaki * oraz + to tak zwane kwantyfikatory, oznaczają ilość wystąpień. Dla przypomnienia C* oznacza dowolną ilość znaków C, również 0 znaków C, zaś C+ to 1 lub więcej wystąpień C. Dla przypomnienia + to kwantyfikator wprowadzony w ERE, zaś * to "uniwersalny" kwantyfikator, występuję zarówno w BRE jak i ERE.

Bywa, że wyszukiwanie za pomocą kwantyfikatorów nie działa tak, jak tego oczekuje programista. Przykład:

<autor1> poszedł o krok dalej od malarza do projektanta obrazów. U szczytu swojej sławy jako malarz, <autor2> miał wielu asystentów

Zdanie z biografii Andy Warhola. Biografia jest zapisana w pliku plik.txt, zadaniem jest zamiana <autor1> oraz <autor2> na Andy Warhol. Pozornie wydaje się to proste, wystarczy wykonać polecenie:

  • sed -n -e 's/<.*>/Andy Warchol/gp' plik.txt

jednak po wykonaniu tego polecenia otrzymamy:

Andy Warhol miał wielu asystentów

a nie o to chodziło, przecież!

Dzieje się tak ponieważ kwantyfikator * jest zachłanny. Stara się znaleźć jak najdłuższe dopasowanie. W tym przypadku jest to dopasowanie od pierwszego znaku < do ostatniego znaku >. Aby poprawie wykonać zadanie wystarczy nieco zmodyfikować polecenie:

  • sed -n -e 's/<[^>]*>/Andy Warchol/gp' plik.txt

[^<]* oznacza dowolną ilość wystąpień każdego znaku z wyłączeniem znaku <.

UWAGA: Standardowe kwantyfikatory POSIX (* oraz +) są zachłanne.


NON-GREEDY QUANTIFICATION

Powyższe problemy spowodowały wprowadzenie tzn. niezachłannych kwantyfikatorów (non-greedy quantyfication). Niezachłanne (non-greedy) kwantyfikatory są oznaczone bardzo podobnie do ich zachłannych (greedy) odpowiedników.

C*?dowolna ilość znaków C, również 0 znaków C
C+? 1 lub więcej wystąpień C
C\{n,\}?nie mniej niż n wystąpień znaku C
C\{,m\}?nie więcej niż n wystąpień znaku C
C\{n,m\}?nie mniej niż n i nie więcej niż m wystąpień znaku C

sed nie wspiera niezachłannych kwantyfikatorów. Aby pokazać ich działanie skorzystamy z perl. Najpierw sprawdźmy jak działa w perl zachłanna *. Po wykonaniu polecenia:

  • perl -p -e 's/<.*>/Andy Warchol/gp' plik.txt

otrzmamy wynik analogiczny do pierwszego z powyższych wywołań sed.

Natomiast gdy zmodyfikujemy * poprzez ?, czyli uczynimy * niezachłanną, to w efekcie wywołania

  • perl -n -e 's/<.*?>/Andy Warchol/gp' plik.txt

otrzymujemy

Andy Warchol poszedł o krok dalej od malarza do projektanta obrazów. U szczytu swojej sławy jako malarz, Andy Warchol miał wielu asystentów

czyli to, co było celem od początku.

CDN...


Tomasz Zin

Na podstawie O'Reilly "Regular Expresion" Tony Stubblebine; August 2003, ISBN : 0-596-00415-X. Wyrażona powyżej opinia jest prywatnym poglądem autora wypowiedzi. Korzystasz na własną odpowiedzialność.