Szukałem ostatnio szybkiego sposobu na podzielenie stringa według jednoznakowego separatora, aczkolwiek w taki sposób, by omijał jego “escape’owaną” formę. W ten sposób mógłbym np. parsować pewne dane tekstowe równocześnie umożliwiając wykorzystanie separatora w samym tekście. Zadanie teoretycznie nie wydawało się trudne, aczkolwiek faktyczne rozwiązanie okazało się co najmniej “nietrywialne”. W dzisiejszym bardzo krótkim i treściwym wpisie chciałbym podzielić się z Wami znalezionym przeze mnie rozwiązaniem.

Fotografia: Maddingue, CC-BY-SA.

PHP: Dzielenie stringa według separatora z wyłączeniem znaku ucieczki.

Rozwiązań oczywiście jest kilka:
  • pętla z wykrywaniem odpowiednich fragmentów stringa,
  • funkcja explode() z łączeniem błędnie podzielonych fragmentów,
  • wyrażenie regularne.
Nie muszę mówić, że ostatnia opcja jest najbardziej atrakcyjna, także zdecydowałem, że pójdę tą właśnie drogą. Biblioteka standardowa PHP udostępnia bardzo fajną funkcję preg_split(), także mamy już w rękach narzędzie, teraz trzeba je tylko uzbroić w odpowiednie wyrażenie regularne. W dokumentacji do wspomnianej funkcji trzeci komentarz opisuje bardzo ciekawy sposób na osiągnięcie tego celu:
If you want to split by a char, but want to ignore that char in case it is escaped, use a lookbehind assertion.

In this example a string will be split by “:” but “:” will be ignored:

<?php $string=‘a:b:c:d’; $array=preg_split(‘#(?<!\):#‘,$string); print_r($array); ?>

Results into:

Array ( [0] => a [1] => b [2] => c:d )

A więc musimy użyć wyrażenia regularnego:

#(?<!\\\)\X#

gdzie X oznacza znak, według którego chcemy podzielić nasz string. Wyjaśnienie mechanizmu działania tego wyrażenia będzie nieco karkołomną sprawą, ponieważ zagadnienie tzw. “lookbehind” i towarzyszącemu mu “lookahead” jest w pewnym sensie “czarną magią” implementacji regexpów. Jest to jedna z tych rzeczy, które potrafię zastosować, jeśli będą potrzebne, aczkolwiek nie wnikam zbyt głęboko w siedzące niżej mechanizmy. Dlatego też nie chcę publikować potencjalnie błędnej interpretacji, pomimo dobrych chęci. Jeśli czujecie się na siłach, zapraszam do wyjaśnień w komentarzach. Polecam lekturę w tym temacie tutaj.

Przy okazji - nie wiem, jak to jest, że parę dni temu opublikowałem harmonogram, a już mam pierwsze spóźnienie. Nie brzmi to zbyt przyjemnie, ale co poradzić - sprawy blogowe kompletnie wypadły mi dzisiaj z głowy. Cóż, miejmy nadzieję, że nie powtórzy się to w przyszłości [i tak się pewnie powtórzy, ale od czego jest wiara we własne siły?]. Dziękuję za lekturę i do zobaczenia w kolejnym wpisie w piątek. ;]