Autor Zpráva
Majkelju
Profil
Zdravím! Mám sestavený regulární výraz pro vybrání textu mezi všemi tagy <t></t> : preg_match_all('/<t>(.*?)<\/t>/s', $text, $match); ... Jak ale udělat, aby mi to ten text vybralo jen v případě, že má alespoň 3 znaky?
Str4wberry
Profil
Stačí použít příslušný kvantifikátor. Tedy {3,}. Hvězdička znamená libovolný počet a otazník ani jednou až maximálně jednou.
juriad
Profil
aby byl regex nežravý, musíš zachovat i otazník: #<t>(.{3,}?)</t>#
a můžeš použít i jiný znak (třeba mřížku) než lomítko pro ohraničení: vyhneš se tak jeho escapování
Majkelju
Profil
Ok, děkuji, takhle to funguje, jediný problém je, když je v tagu <t> m2</t>, tak to vybere taky, protože tu mezeru to vlastně počítá taky...nedá se tam přidat něco jako trim() ?
Joker
Profil
Majkelju:
trim by šel simulovat, když použiji juriadovo řešení:
#<t>(\s*)([\S]{3,}?)(\s*)</t>#
(žádný nebo nějaké bílé znaky, pak alespoň 3 znaky co nejsou bílé znaky a pak zas žádný nebo nějaké bílé znaky).

Oprava, i za druhým (\s) měla být hvězdička
oprava 2, přehnal jsem to s negacemi, \S je všechno kromě bílých znaků, takže už není třeba negovat.
juriad
Profil
#<t>\s*(.{3,}?)\s*</t>#

\s: Match a whitespace character
tedy mezery, tabulátory a podobnou havěť bude přeskakovat


Joker:
nedávej whitespacy do závorek, zbytečně plýtváš referencí, kterou nikdy nepoužíješ

na konci, u druhého \s ti chybí hvězdička

uprostřed není třída [^\S], takto jsi definoval, že střed má obsahovat alespoň tři whitespacy,
dokonce tam nemůže být ani [^\s] by pak střed nesměl obsahovat ani mezeru, například: <t> čtyři slova oddělená mezerami </t>
protože střed je stejně nežravý, takže tam nemusí žádná třída být, protože whitespacy stejně končit nebude
Joker
Profil
[#6] juriad:
Bude to takhle fungovat?
Podle mě třeba <t> x </t> tomu reguláru vyhoví, protože \s* vyhoví i prázdný řetězec a to x s mezerami vyhoví té vnitřní závorce.

Ale napadá mě, že s tím mým výrazem zas nebudou fungovat ani mezery uvnitř toho textu.
dotatek, zmíněnou hvězdičku a ^\S jsem mezitím už opravil.
Majkelju
Profil
Tak nevím, co tam mám za kiks, ale Jokerovo řešení mi nevybírá nic a juriadovo mi naopak vybere kromě textu i nějaké další tagy navíc...

Původní text vypadá takto:
<vv><r><t>plocha NK: </t><v>50*11</v><vy>A</vy><t> m2</t></r><r><v /><t>tloušťka NK: </t><v>0,75</v><vy>B</vy><t> m</t></r><r><t>kubatura: </t><v>a*b</v><vy>C</vy><t> m3</t></r></vv>

Jokerovo řešení:
 50*11 = 550
0.75 = 0.75
a*b = 0

juriadovo řešení:
plocha NK:50*11 = 550
m2</t></r><r><v ></v><t>tloušťka NK:0.75 = 0.75
m</t></r><r><t>kubatura:a*b = 0

Vypadat by to mělo jako:
plocha NK:50*11 = 550
tloušťka NK:0.75 = 0.75
kubatura:a*b = 0

DODATEK: Jde tu vlastně jen o ty nápisy, regex na výběr čísel mi funguje a neuvádím ho tu...
Joker
Profil
Majkelju:
No, další komplikace je, že:
<t>x</t> -něco dalšího-<t>y</t>
označená část vyhoví tomu výrazu.
Jinak řešeno, když v nějaké značce <t> budou méně než tři znaky, pořád tomu výrazu může vyhovovat když se vezme i koncová značka a ještě další obsah až po koncovou značku příštího <t>.

Navíc mám dojem, že ta podmínka ve skutečnosti nemá být značka <t> s více než třemi znaky uvnitř, ale první značka <t> uvnitř značky <r>.
Kdyby třeba kubatura byla v cm3, zase to nebude fungovat.

Obecně by se pro zpracování XML měl používat XML parser a regulární výrazy jen pro opravdu triviální situace.
Jan Tvrdík
Profil
Majkelju:
Proč nepoužiješ XMLParser? Např. SimpleXml.
Majkelju
Profil
O XMLParseru jsem ještě neslyšel...to se musí nějak nainstalovat? Nebo ta podmínka by se nedala nějak rozumně upravit?
EDIT: Joker: Ano, taková podmínka by byla asi jednodušší... To se taky dá pomocí regexu? Omlouvám se, že jsem úplně mimo, ale ani po projití značek, které může výraz obsahovat, z toho nejsem moc moudrý...


Ještě mě napadlo, že by možná šlo umazat ten nechtěný kus textu (abych to nemusel celé předělávat na ten parser)...to myslím nějak jde, ne? Aby to smazalo vše od začátku až po uzavírací zobáček tagu <t>. Je to asi prasárna, ale jde v podstatě jen o obyčejný výpis textu, tak s tím nechci strávit půl dne...
Jan Tvrdík
Profil
Majkelju:
O XMLParseru jsem ještě neslyšel...to se musí nějak nainstalovat?
Pokud nemáš speciálně zkompilované PHP, tak tam SimpleXML budeš mít k dispozici. Česky jsem o SimpleXML našel
programovani.blog.zive.cz/2009/12/simplexml-jednoduse-na-xml-v-php-1dil
programovani.blog.zive.cz/2009/12/simplexml-jednoduse-na-xml-v-php-2dil
www.devbook.cz/php-cteni-xml-tridou-simplexml


Třeba takto nějak:
<?php
$s = '<vv>
    <r>
        <t>plocha NK: </t>
        <v>50*11</v>
        <vy>A</vy>
        <t> m2</t>
    </r>
    <r>
        <v />
        <t>tloušťka NK: </t>
        <v>0,75</v>
        <vy>B</vy>
        <t> m</t>
    </r>
    <r>
        <t>kubatura: </t>
        <v>a*b</v>
        <vy>C</vy>
        <t> m3</t>
    </r>
</vv>';

$xml = simplexml_load_string($s);

foreach ($xml->r as $r) {
    foreach ($r->v as $v) {
        $v = trim($v);
        if (empty($v)) continue;
        echo "V: $v<br>\n";
    }

    foreach ($r->t as $t) {
        echo "T: $t<br>\n";
    }
}
Majkelju
Profil
Jan Tvrdík:
Aha, díky :) Jinak momentálně jsem to metodou pokus-omyl vyřešil pomocí
echo preg_replace('#.*?<t>#', "", $pole[$i]);
Ale ten parser se mi bude určitě ještě hodit do budoucna, s xml nekončím :)
peta
Profil
Treba takovyto priklad ti pomuze s xm parserem a prestanes resit reg vyrazy.
http://peter-mlich.wz.cz/web/php/pr/wheather-wunderground.php
http://peter-mlich.wz.cz/web/php/pr/wheather-wunderground.txt

preg_match_all('/<t>(.*?)<\/t>/s', $text, $match);
#<t>(\s*)([\S]{3,}?)(\s*)</t># - kdyz tam nechas ty zavorky, tak match vybira zavorku po zavorce 1, 2 i 3 a jestli jsi tam nechal $match[1], tak je jasne, ze ti to nejde. Takze bych ty zavorky zrusil
#<t>\s*([\S]{3,}?)\s*</t>#

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: