Reptile ReX
27.12.2010, 14:55:00
Witam mam pewien problem, bardzo się staram, ale nadal nie mogę pojąć wyrażeń regularnych.
Tzn proste przykłady są jasne, ale chodzi np o wyciągnięcie jakiś danych ze strony www.
Wtedy już mieszam się ze wzorcem.
A więc posiada ktoś jakiś kurs dzięki któremu dowiedziałbym się jak popranie konstruować tego typu wzorce?
A może ktoś ma chwilkę i wytłumaczy mi to bardziej dokładnie, przeglądałem manual, różne kursy i książki, ale albo jest to słabo wytłumaczone, albo chaotycznie... albo po prostu mój mózg nie pracuje na tych falach.
Z góry dziękuje za pomoc.
Athlan
27.12.2010, 15:06:29
Kiedyś @Matix przesłał mi kod, który postanowiłem nieco zmodyfikować. Używasz tego jak selectorów jQuery, tylko przez metodę get() i query(). Potężne narzędzie używające
domxPath.
http://athlan.pl/code/VframeLib_Map.ClassBaw się, dumpuj, bo dajemy za darmo ; )
Athlanie, co Twój post ma wspólnego z problemem autora tematu?
Reptile ReX -> wyrażenia regularne nie są niczym trudnym... pod warunkiem, że się rozumie ich podstawy matematyczne. Nie wiem czy spotkałeś się z pojęciem automatu skończonego. Jest to taki prosty model realizacji obliczeń, który ma dużo mniejsze możliwości, niż to, co reprezentują komputery, ale za to jest dużo prostszy w analizie i "programowaniu". Automat skończony możesz sobie wyobrazić jako pewną maszynkę, która patrzy na określony znak i znajduje się w określonym stanie. W każdym kroku przesuwa się do przodu na kolejny znak tekstu i w zależności od tego, co tam się znajduje, może zmienić swój stan, lub nie. Stan to po prostu liczba, która ma jakieś tam znaczenie dla automatu. Ważne, że w momencie dojścia do końca tekstu automat musi znaleźć się w tzw. "stanie akceptującym", co oznacza, że rozpoznał podany tekst jako poprawny.
Najprostszy przykład automatu to rozpoznawanie tekstów zaczynających się od dowolnej liczby zer, po których następuje jedynka i znów dowolna liczba zer. Ustawiamy automat na pierwszy znak tekstu i stan na "q1". Patrzymy, co jest pierwszym znakiem, zmieniamy stan, patrzymy na drugi, zmieniamy stan itd. zaś wszystko według takich regułek:
("0", q1) -> q1 // ten stan rozpoznaje pierwszy ciąg zer
("1", q1) -> q2 // gdy w stanie q1 napotkamy 1, przechodzimy do kolejnego stanu
("0", q2) -> q3 // i w tym stanie oczekujemy, że następne będzie 0
("0", q3) -> q3 // w stanie q3 rozpoznajemy drugi ciąg zer i jest to też stan akceptujący
Zauważ, że nie ma tu wszystkich wariantów. Jeśli w stanie q1 napotkamy znowu "1", jest to sytuacja błędna. Nie ma przejścia, zatem automat kończy działanie z błędem, że słowo jest nieprawidłowe. Spróbuj prześledzić sobie działanie tego prostego automatu dla różnych ciągów zer i jedynek.
Ograniczenia takiego automatu:
- Można poruszać się po tekście wyłącznie w przód.
- Nie można zapamiętywać żadnych dodatkowych informacji, poza tymi kodowanymi jako stany.
Co to oznacza: że np. nie da się skonstruować automatu, który rozpoznaje teksty, gdzie najpierw jest np. "n" jedynek, a później "2n + 5" zer, ponieważ nie możemy nigdzie zliczyć liczby jedynek (wymagałoby to nieskończonej liczby stanów i nieskończonej tablicy przejść, tymczasem muszą one być skończone). Za to np. możemy już skonstruować automat, który rozpozna ciąg jedynek i następujących po nim zer takich, że zarówno liczba jedynek jak i zer jest parzysta. Wczytujemy jedynkę, przechodzimy do stanu "nieparzysty". Wczytujemy kolejną jedynkę, przechodzimy do "parzysty" i tak w kółko, a gdy zaczynają się zera, rozważamy dwa przypadki: skończyliśmy wczytywać jedynki w stanie parzysty/nieparzysty.
Po co to wszystko? Ano dlatego, że wyrażenia regularne to po prostu wygodny sposób zapisu "programów" dla automatów skończonych. Dla każdego automatu skończonego da się zbudować wyrażenie, dla każdego wyrażenia regularnego da się zbudować taki automat skończony (maszynę stanów). Wyrażenie regularne opisuje po prostu, co ma się znaleźć w kolejnych partiach analizowanego napisu, używając najprostszych operacji:
- Alternatywa ("1|0" oznacza: może być "1" lub "0")
- Sklejanie ("10" oznacza: po "1" muszą wystąpić "0")
- Gwiazdka Kleene'go: ("1*" dopasowuje "", "1", "11", "111", "1111" "11111" itd.)
Wspomniane wyrażenie akceptujące parzystą lub nieparzystą liczbę jedynek i zer może być wyrażone następująco:
(11)*(10(00)*)|(11(00)*)
Czytaj to sobie od lewej do prawej, próbując dopasować jakiś napis i patrząc na powyższe trzy rzeczy (nawiasy grupują obliczenia, jak w artymetyce) i zauważysz, że to prawda.
TYLE. To jest cała filozofia wyrażeń regularnych, a rzeczy typu biblioteka PCRE po prostu wzbogacają ideę o kilka dodatkowych narzędzi ułatwiających pracę z rzeczywistymi napisami w normalnych programach (np. definiowanie zbiorów dopuszczalnych znaków). Innymi słowy, uczcie się ludzie matematyki bo zginiecie jak babka w Czechach.
Jeśli już utworzyłeś wyrażenie regularne , a Masz wątpliwości co do działania ,możesz przetestować je :
na tej stronie.
thek
27.12.2010, 21:09:26
Offtop: Zyx... takiego wyjaśnienia czym są regexp jak żyję nie widziałem i nie słyszałem. Szacuneczek, zwłaszcza, że zawsze byłem za matmą, nawet gdy mi dawała kiedyś w kość przy dystrybuantach czy ortogonalizacjach i normalizacjach macierzy

Szkoda tylko, że może 5% tutaj piszących rozumie co właśnie napisałeś
A co mi tam, opiszę taki automat w PHP:
'0.q1' => 'q1',
'1.q1' => 'q2',
'0.q2' => 'q3',
'0.q3' => 'q3'
);
$state = 'q1';
for($i = 0; $i < $length; $i++)
{
if(!isset($stateTable[$text[$i].'.'.$state])) {
die('Blad na znaku '.$i); }
$state = $stateTable[$text[$i].'.'.$state];
}
if($state == 'q3')
{
echo 'Zaakceptowano; słowo pasuje'; }
Nawiasem mówiąc, nie jest to pierwsza osoba, której tłumaczę ideę wyrażeń regularnych w ten sposób. Automaty skończone są debilnie proste, zwłaszcza jak się je narysuje w formie diagramu, a pozwalają zrozumieć, co tak naprawdę można zrobić przy pomocy wyrażeń regularnych i jak to się dzieje, że one działają. Dotąd nie było większych problemów ze zrozumieniem.
Athlan
27.12.2010, 21:32:23
@Zyx dobrze prawi, właśnie w taki sposób działają wyrażenia regularne. Może niezbyt praktycznie, ale warto mieć elementarną wiedzę na temat tego, co się używa. W zaawansowanych przypadkach (optymalizacja) ta wiedza staje się podstawową (i nie tylko regexp). Nawiasem mówiąc, warto poczytać o
http://pl.wikipedia.org/wiki/Maszyna_Turinga