Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Mały zgrzyt z preg_matchem :)
Forum PHP.pl > Forum > PHP
kovalson
Witam, starannie rozglądam się w internecie, zanim o cokolwiek tutaj zapytam, bo wiem, że niektóre pytania są banalne, ale od tygodnia staram się rozwiązać problem preg_matcha. Zająłem się parsowaniem logów chatu gry (Minecraft), tak dla czystej przyjemności i w efekcie otrzymuję z logu:
  1. 2011-05-29 17:44:36 [INFO] <gracz> jakis tekst

takie coś:
  1. 2011-05-29 | 17:44:36 | SAY | gracz: | jakis tekst
Oczywiście wszystko zapisane w tabeli itd.

Jak łatwo się domyślić, znajduję znak "<", ">" oraz to co jest między nimi, żeby określić nick, a po spacji wiadomość. Preg_match wygląda tak:
  1. if(preg_match("#([0-9]{4})-([0-9]{2})-([0-9]{2})\s([0-9]{2}):([0-9]{2}):([0-9]{2})\s(\[INFO\])\s(\<)(.{1,})(\>)\s(.*)#", $line, $result))

Cały mój misterny plan ugrzązł w tym miejscu (fragment logu):
  1. 2011-05-29 17:49:37 [INFO] <gracz> jakis tekst > inny tekst


A mój skrypt parsuje to na takie coś:
  1. 2011-05-29 | 17:49:37 | SAY | gracz> jakis tekst: | inny tekst


Czyli uznaje dalszy ciąg, aż do znaku ">", jako nick, co ciekawe przed faktycznym nickiem dopisując ">", a nie po tym ciągu.

Nie mam pojęcia o co chodzi, próbowałem na wiele sposobów ograniczyć występowanie znaku ">", np. przez "{,1}", ale dalej nie chce współpracować.

Mam nadzieję, że napisałem jasno i wybaczcie, że się tak rozpisuję, ale chcę, żeby wszystko było jasne, dlatego małe wprowadzenie uznałem za stosowne. Z góry dziękuję za pomoc smile.gif
pamil
Przykład:
Kod
/<([^>]+)>/

Pobiera wszystko od znaku < do pierwszego znaku >.
abort
Masz w pewnym miejscu w wyrażeniu ciąg znaków (.{1,}) - ma on za zadanie dopasowanie nicka gracza.
Dopasowuje on dowolny znak (".") wystepujący conajmniej raz "{1,}".
Problem w tym, że taka instrukcja jest "zachłanna" - dopasowuje najwięcej znaków pasujących do wzorca - w praypadku, kiedy gracz użyje ">" w wypowiedzi, dopasuje także część wypowiedzi.

1. zamień w/w frament na (.*?) i powiedz, czy pomogło.
2. alternatywnie nie zamieniaj, ale dodaj za ostatnim "#" literkę "U" (zmienia tzw. "zachłanność" w ramach całego wzorca)
pamil
Cytat(abort @ 15.08.2012, 09:34:14 ) *
1. zamień w/w frament na (.*?) i powiedz, czy pomogło.

Pomoże.
kovalson
Voila, wielkie dzięki dla Ciebie abort, bo męczyłem się z tym przez tydzień. Widzę, że trochę od złej strony się za to zabierałem. A mógłbyś mi jeszcze wytłumaczyć jaką funkcję (w tym przypadku) pełni "?" na końcu? Chcę to zrozumieć w 100%, żeby później tego błędu nie powtarzać wink.gif. Jeszcze raz wielkie dzięki smile.gif
grzes999
? oznacza, że podany wzorzec może wystąpić raz albo w ogóle.
I na przyszłość polecam stronę bardzo dobre narzędzie do sprawdzania wyrażeń regularnych.
abort
http://www.php.net/manual/en/reference.pcr...n.modifiers.php
Poszukaj też o PCRE w ogólności, a także o słowach "greedy" i "ungreedy" (oczywiście w kontekście PCRE)

@grzes999 w ogólności tak, ale w kontekście wyrażenia "(.*?)" znaczy już zupełnie coś innego (patrz wyżej)
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.