Autor Zpráva
danhill
Profil
Ahoj,
opět válčím s reg. výrazy a nedaří se mi.
Mám různé typy zápisů na vstupu.
Konkrétně tyto:
Multi-cache
Multi
MultiCache
Multi-Cache
Multi cache
Multi Cache

a stejné možnosti u mnoho dalších
Mystery-cache
Mystery
MysteryCache
.
.
.
dále
Wherigo-cache
atd atd

Pomocí regulárního výrazu potřebuji vytáhnout vždy to první slovo.
Nejlepší by bylo to první slovo definovat, respektive tak aby se dalo kdyžtak přidat další první slovo a aby nenastal problém v momentě,kdy by první slovo také obsahovalo c nebo C
Ale to není podmínkou, mě to nechodí ani bez definování prvního slova.
Prosím o pomoc s tímto reg. výrazem.
Zkouším třeba
(.*?)[ \-\C\c]+(.*?)
Ale nechodí to správně.
Moc děkuji.
juriad
Profil
Pokud ty výrazy máš někde samostatně a nepotřebuješ je hledat v textu, asi bych na to šel jednodušeji:
<?php

foreach (file('f', FILE_IGNORE_NEW_LINES) as $text) {
    # převeď všechny znaky na malé, zahoď slovo cache, zahoď vše co není písmeno
    $cache = preg_replace('/[^a-z]/', '', preg_replace('/cache/', '', strtolower($text)));
    echo "$text: $cache\n";
}
danhill
Profil
Ne ne, právě že je hledám v textu:
Mám něco takového:
    preg_match_all("'<img src=\"/images/WptTypes/(.*?)\" alt=\"(.*?)\"'si", $htmlcache, $match);
        foreach($match[2] as $val)    {
        echo $val."<br>";
    }



Kde právě v alt= je to požadované sousloví.


A první písmeno bych právě velké naopak potřeboval ...
juriad
Profil
Jelikož máš oblast vyhrazenou uvozovkami, můžeš použít:
preg_match_all('#<img src="/images/WptTypes/(.*?)" alt="([a-z]*)[ -]?(?:cache)?"#si', $htmlcache, $match);

Pozn. Regulární výrazy vždy zapisuj mezi apostrofy, ušetříš si escapování a pro ohraničení můžeš použít jakýkoli vhodný znak, často se používají: /~#.

To velké písmeno pomocí regexů v PHP neuděláš. Ale to ti nevadí:
echo ucfirst($val), "<br>";
danhill
Profil
wooow ... Opět smekám ... Děkuji pěkně ...
Nádhera ...
A já se s tím s* tři hodiny.
JS a regexy, to je moje smrt prostě ...


Jen doplňující otázka pro mou zvědavost,
pokud bych oblast neměl vyhrazenou uvozovkami, kdybych například hledal to stejné mezi html tagy <h1>Multi-cache</h1> tak to v praxi znamená co?
danhill
Profil
Tak se to schválně zkouším pochopit,ale prostě ne ...
Ještě poprosím o pomoc ... V tom escapování úplně jako logiku nevidím.
Přitom mi to příjde napsané stejně jako příklad výše,jen tam nejsou ty uvozovky, to je pravda ...

preg_match_all('#<li class="li__cache-type">([a-z]*)[ -]?(?:cache)?</li>#si', $htmlcache, $match);
juriad
Profil
Ano, je to velice podobné.

Escapování. Vidíš, že teď v tom regexu není jediné zpětné lomítko a je o dost čitelnější. Apostrofy jsou vhodnější, protože tam existují jen dvě escape sekvence: \\ a \'. Ve většině případů bude stačit napsat méně zpětných lomítek.

Ohledně toho ohrazení uvozovkami. Kdybys hledal ve volném textu, tak ti to najde třeba spojení „dobra cache“, což asi nechceš. Právě to, že je to uvnitř atributu (nebo uvnitř položky seznamu, to je jedno) zajistí, že to omylem nenajde něco, co není typ cache.
danhill
Profil
No ale takto nefunguje to ...
To s těmi křížky jako chápu, že pak nemusím escapovat pomocí \ ,určitě je to přehlednější, ale stejně mi někde v případě vyhledávání mezi html tagy nějaký escape chybí ...
Podle mě konkrétně minimálně v </li> ,ale ještě někde,kde to nevidím ... :(
juriad
Profil
danhill:
Zpracovávat HTML pomocí regexů je ošidné, protože to klidně může obsahovat spoustu mezer a odřádkování, se kterými nepočítáš.
Dodej ukázku přesného HTML, které zpracováváš, případně pošli odkaz na stránku, odkud to pochází.

Ne, nikde nic nechybí, regex je v pořádku, jen mu dáváš jiné vstupy, než očekává.
danhill
Profil
Hledám tohle:
<li class="li__cache-type">Multi-cache</li>
ze stránky :
coord.info/GC1ZYF5
juriad
Profil
Na odkázané stránce nic takového není. Pomoci JS přesměrovává na www.geocaching.com/geocache/GC1ZYF5_v-ozvene, na ní (pokud je uživatel nepřihlášený) se nachází:
            <li class="li__cache-type">                
                Multi-cache
            </li>

Použij regex:
preg_match_all('#<li class="li__cache-type">\s*([a-z]*)[ -]?(?:cache)?\s*</li>#si', $htmlcache, $match);
TomášK
Profil
A určitě to chceš dělat regulárními výrazy?

stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags
simplehtmldom.sourceforge.net (nemám vyzkoušené, nepoužívám php)

OT: Není tu někde diskuze o používání regulárních výrazů na parsování html? Čekal bych, že ve FAQ bude, ať to lidi nedělají, ale co jsem zaznamenal, tak se nad tím nikdo nepozastavuje.
danhill
Profil
ono to tam přesměruje,ano ...

No jasně whitespace ... že mi to nedošllo ...
Děkuji, už to chápu.
Teda pro tento případ to chápu,obávám se,že až budu hledat něco jiného,zase to bude porod :)


TomášK:
Nevím o jiné možnosti jak to udělat :(
juriad
Profil
TomášK:
Zrovna v případě, kdy se jedná o jeden jediný tag to regexy jde řešit ještě pěkně. Použít knihovnu pro parsování HTML na celou stránku by byl overkill. Kdyby už nějak dokázal vyříznout jen relevantní část, může ji zpracovat rovnou pomocí regexů.

danhill:
Výborně. Neboj se znovu zeptat.
TomášK
Profil
Alternativa je použít DOM parrser. Ten druhý odkaz je knihovna pro parsování DOM, pak by mohlo jít něco jako

$html = file_get_html(' www.geocaching.com/geocache/GC1ZYF5_v-ozvene');
echo $html->find('li.li__cache', 0)->innertext  // Multi-cache

Ale jak jsem psal, v php to vyzkoušené nemám, je to první, co jsem našel na googlu. Možná jsou lepší knihovny, případně i něco přímo v php.

juriad
Pokud to potřebuje externí závislost, můžou být regexpy rychlé řešení. Ale jinak výhody nevidím - jsou náchylnější na chyby, méně přehledné, hůř se v tom ošetřují třeba chybějící uvozovky okolo hodnot apod. Možná budou o fous rychlejší, ale i ten DOM parser to naparsuje rychleji než se to stáhne.
danhill
Profil
Ještě malá drobnost.
preg_match('#<img src="/images/WptTypes/(.*?)" alt="([a-z]*)[ -]?(?:cache|geocache|hybrid)?"#si', $htmlcache, $match);
Funguje bezvadně až na jeden případ.
V momentě,kdy jsou slova odděleny pomlčkou nebo mezerou,tak to samozřejmě šlape. To má za úkol [ -]
Ale problém nastane,když mám napsáno MultiCache bez jakéhokoli oddělovače.
Tak se chci zeptat,jestli se do toho regexu nedalo dopsat ještě aby zahodil slovo cache,pokud tam je a pokud není oddělovač mezera nebo -.
Zkoušel jsem třeba
preg_match('#<img src="/images/WptTypes/(.*?)" alt="([a-z]*)(cache)|[ -]?(?:cache|geocache|hybrid)?"#si', $htmlcache, $match);
a podobně,ale to mi nechodí ...
Děkuji moc.
juriad
Profil
danhill:
Ok, stačí přidat otazník:
preg_match('#<img src="/images/WptTypes/(.*?)" alt="([a-z]*?)[ -]?(?:cache|geocache|hybrid)?"#si', $htmlcache, $match);
Ten značí v kombinaci s hvězdičkou, že se má sežrat co nejméně.
danhill
Profil
Děkuji moc. Funguje bezvadně ...

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: