[regex] Wyrażenie rozkładające stringa na części

0

Mam takiego stringa:

/id=13/module=download/action=show/message=error/date=now/

i napisałem sobie wyrażenie, które miało to wrzucić do tablicy:

preg_match_all( "/\/(.*)=(.*)\//U", $string, $matched, PREG_SET_ORDER );

ale wynik jest taki:

Array
(
    [0] => Array
        (
            [0] => /id=13/
            [1] => id
            [2] => 13
        )

    [1] => Array
        (
            [0] => /action=show/
            [1] => action
            [2] => show
        )

    [2] => Array
        (
            [0] => /date=now/
            [1] => date
            [2] => now
        )

)

I widać, że nie jest tak jak powinno być. Jak zmienić to wyrażenie by dopasowywało wszystkie pary?

0

hehe, fajny temat :)

problemem jest to, że wyrażenie pochłania także slash - więc zjadane jest to tak:
<font color="blue">/id=13/</span>module=download<font color="blue">/action=show/</span>message=error<font color="blue">/date=now/</span>

"module=download" i "message=error" nie mają początkowego slasha dlatego nie są dopasowane

można to rozwiązać np. za pomocą lookbehind oraz lookahead, które mają zerową długość dopasowania - czyli nie zjadają dopasowanych ciągów.

Mylący dla mnie jest parametr U ale już go zostawię jak chcesz :P
Poza tym - lepiej używaj negacji klas zamiast leniwych gwiazdek (jeśli tylko można, bo nie zawsze) - znacznie szybciej!

Łącząc wszystko dochodzimy do takiego wyrażenia [<font color="darkblue">ostrzegam, nie miałem czasu przetestować - jak coś nie tak, to napisz - poprawi się</span> ;)]

"/(?<=/)([^=])=(.)(?=/)/U"

ale chyba nawet nie trzeba lookahead jak tak patrzę
"/(?<=/)([=])=([/])/U"

Nie dam głowy, czy w lookahead i lookbehind slashe tracą znaczenie specjalne czy nie - jeśli nie, to poprzedź je backslashami.

0
Warning: preg_match_all() [function.preg-match-all]: Unknown modifier ')' in C:\apachefriends\xampp\users\kolonie\public_html\index.php on line 4

Nie do końca rozumiem wyrażenia regularne, nawet po przeczytaniu kilku kursów (jakoś ich nie potrafię zrozumieć). Marooned może masz jkąś inną propozycję [???] bo widzę, że jesteś o wiele lepiej zorientowany w temacie.

Dlaczego się uparłem na regex'epa: ponieważ nie wiem ile będzie takich par nazwa=wartość oddzielonych od siebie /, a potrzebuje je wrzucić do tablicy, która będzie wyglądała mniejwięcej tak:

Array {
    [nazwa] = wartość
    [nazwa2] = wartość2
    [nazwan] = wartośćn
}

Więc według mnie najlepszym rozwiązaniem tutaj było by zastosowanie regex'pa (no chyba, że jest coś prostszego i szybszego, to porszę oświećcie mnie), ale mogę się mylić....

Z góry dzięki za pomoc

0

ok, były 2 błędy
pierwszy to Ci pisałem [!!!] - wystarczyło poprzedzić slashe backslashami

drugi wynikł z tego, że rzadko stosuję lookbehind

<font color="blue">"/(?<=/)([=]?)=([/])/"</span>

sprawdziłem, działa
zniknął parametr <font color="blue">U</span> aby nie mylić.
opis? proszę bardzo :)

<font color="blue">(?<=/)</span> - dopasowuje <font color="blue">/</span> przed resztą wyrażenia, ale nie pochłania go [!!!]
<font color="blue">([^=]?)</span> - pierwsze backreference - łapie ciąg od znaku za <font color="blue">/</span> do znaku przed pierwszym <font color="blue">=</span>
<font color="blue">=</span> - łapie <font color="blue">=</span>
<font color="blue">([^/]
)</span> - pasuje do ciągu od znaku za <font color="blue">=</span> do znaku przed następnym <font color="blue">/</span>

tu właśnie się zdziwiłem, ale po przemyśleniu wszystko jest ok - dlaczego nie napisałem <font color="blue">([^/]*?)</span> aby złapać ciąg do pierwszego najbliższego <font color="blue">/</span> ? ponieważ pierwszym najbliższym <font color="blue">/</span> jest znak na samym początku! to właśnie cecha lookbehind - nie zjadło nam tego slasha dlatego ta część może go dopasować

0

no tak tylko jesli chodzi o wyrazenia regularne warto sie zastanowic kiedy je uzywac a kiedy po prostu nie poniewaz sa znacznie wolniejsze niz standardowe funkcje wykonujace konkretna operacje np tutaj wyrazenie regularne mozemy zastapic poprzez proste strtok i explode:

function podziel($str)
{

$s = strtok($str, "/");
while($s)
{
$s = explode("=", $s);
$arr[$s[0]] = $s[1];
$s = strtok("/");
}
return $arr;
}

i wszystko nie wspomne ze jest o wiele szybszy niz wspomniane wyzej wyrazenie regularne do takich rzeczy sie ich nie stosuje tylko do skomplikowanych operacji na tekscie gdzie napisanie wlasnego algorytmu mija sie z czasem i zachodem a w przypadku zastosowania wyrazenia regularnego jest o wiele prostsze w implementacji w tym wypadku jak widac zbedne

0

no i tu się w 100% zgadzam, bo zapanowała jakaś dziwna moda na używanie wyrażen regularnych gdzie popadnie, bo w sumie ładnie to wygląda i jeśli komuś nie wiele zależy na milisekundach a skrypt jest wykonywany na cudzym serwerze to jest wszystko ok, ale naprawdę one strasznie marnują zasoby i gdzie to nie jest konieczne to lepiej ich nie używać

0

Ja nie przeczę - nawet nie zastanawiałem się nad tym, czy da się inaczej - sądzę, że angel wie co można i czego nie i skoro prosił o regexp to mu je dałem - ale zgadzam się z wypowiedziami powyżej.

0

Marooned, ty regexp-maniaku, ilekroć mam do zrobienia regexpa widzę przed oczami twojego avatara.

0

Głównie chodziło o sprawdzenie tego czy dobrze zrozumiałem kurs regexp'ów (jak się okazuje wcale). Później popróbowałem obydwa sposoby i jak na razie z regexp chyba na razie zrezygnuję... Marooned może znasz jakiś kurs dla topornych [???]

Dzięks za pomoc.

0
Kapustka napisał(a)

Marooned, ty regexp-maniaku, ilekroć mam do zrobienia regexpa widzę przed oczami twojego avatara.
buachacha [green]
nie zawsze było tak różowo - obadaj to: http://marooned.neostrada.pl/4prog/iglu.htm [napisane 2003-08-10]
szczególnie linijka:

if(text.match(/^[0-9]+$/g)) //dzięki piechnat za wyrażenie reg.
:D no ale nikt nie rodzi się z umiejetnościami :)

angel2953 napisał(a)

Marooned może znasz jakiś kurs dla topornych

Najlepsza pod słońcem stronka o regexp - z niej doszlifowałem umiejętności i poznałem pełną składnię Perla [a nie nędzną namiastkę POSIX czy też totalnie podstawowe regexp :>]
A wcześniej? losowe stronki z google i męczenie piechnata i Vogela [to te 2 lata temu]

1 użytkowników online, w tym zalogowanych: 0, gości: 1