Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: RegExp dzielenie ciągów
Forum PHP.pl > Forum > PHP
session
Witam,
Moim celem jest podzielenie ciągu w którym separatorem jest na przykład taki znak: | ale pod warunkiem, że przed tym znakiem nie występuje np. \

  1. $str='string1\|string2|string3';
  2. $pattern="/[^\\\]\|/";
  3. $matches=preg_split($pattern, $str);
  4. print_r($matches);

Kod prawie działa prawidłowo, niestety ucinany jest znak występujący przed |, czyli: "2" w ciągu: "string1\|string2". Chciałbym też, żeby skrypt usuwał/pomijał znak: "\", jeśli występuje on tuż przed "|", niestety lookahead nie wszędzie jest prawidłowo wspierany, dlatego zdecyduję się chyba na użycie osobnej funkcji, chyba że można to osiągnąć przy zastosowaniu odpowiedniego wzorca rolleyes.gif .

Wiem jak osiągnąć mój cel innymi sposobami tj. explode + pętla foreach + instrukcja warunkowa, ale interesuje mnie wykonanie tego za pomocą wyrażeń regularnych.

Macie jakieś pomysły na prawidłowy pattern ? wink.gif
Crozin
Wyrażenia regularne nie są najlepszym rozwiązaniem w tym wypadku.

1. Zamiast z lookahead powinieneś skorzystać z lookbehind.
2.
  1. $input = '1111|2222|3333\\|3333|4444|55\\55|6666';
  2.  
  3. $array = preg_split('#(?<!\\\\)\\|#', $input);
  4.  
  5. print_r($array);
3. Nadal będziesz musiał wykonać dodatkową pętlę, która usunie znaki ucieczki sprzed znaku separatora:
  1. foreach ($array as &$element) {
  2. $element = str_replace('\\|', '|', $element);
  3. }
4. W powyższym kodzie brak wsparcia dla znaku ucieczki przed znakiem ucieczki, tj. następującego przypadku:
Kod
222\\|3333
no_face
Jak to wszystko Twoje to zmien seperator:

  1. $str="string1|string2||string3";


lub jakikolwiek inny, a pozniej tylko poczestujesz to o wiele szybsza funkcja:

  1. explode("||", $str);
com
no_face
Cytat
Wiem jak osiągnąć mój cel innymi sposobami tj. explode + pętla foreach + instrukcja warunkowa, ale interesuje mnie wykonanie tego za pomocą wyrażeń regularnych.

autor napisał że explode mu nie odpowiada smile.gif
session
@Crozin dzięki za odpowiedź smile.gif .

W odniesieniu do Twojego posta:

3. Właściwie miałem str_replace tuż przed wyświetleniem stosować, dlatego też pętla nie byłaby potrzebna, ale to mało istotne wink.gif
4. Tak właściwie to z czego to wynika ? Chyba przy okazji w całym ciągu tak się dzieje. Wynika to z natury backslashy, że domyślnie służą do innych celów czy wynika to z samego wyrażenia ?

Unikam explode ponieważ w zdecydowanej większości przypadków w ciągu nie będzie w ogóle występował znak: | , ale jeśli się on już pojawi skrypt musi odpowiednio na niego zareagować, ale nie mogę też zabrać żadnego znaku z zestawu, więc musi być możliwość potraktowania znaku: | po prostu jako tego znaku bez modyfikacji. W dodatku byłem ciekaw, bo jak wiadomo explode nie umożliwia np negacji znaku, a sama możliwość wykorzystania wyrażenia jako takiego jakby separatora wydaje się dla mnie co najmniej intrygująca wink.gif . A co myślicie o preg_match ? Zadziałałoby identycznie ?
Crozin
Ad. 3. Mimo wszystko powinieneś mieć tą pętlę. Pomiędzy wstępnym przetworzeniem danych, a dokończeniem tego procesu i wyświetleniem danych może w przyszłości dojść jeszcze jakiś kod - tworzysz potencjalne miejsce dla błędów.
Ad. 4. Wynika to z użycia niewłaściwego narzędzia, tj. wyrażeń regularnych, w danym zadaniu. Same ukośniki są znakiem jak każdy inny, nie mają żadnej specjalnej natury w tym kontekście.

---

1. Użycie preg_match() niczego nie zmieni.
2. Napisz po prostu zwykły parser dla tego formatu - to raptem kilkanaście linii kodu. Będzie działać wolniej od dowolnej kombinacji wyrażeń regularnych, explode'ów i innych, ale to już wynika powolności samego PHP.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.