Ktorý RE sa použil pri alternatíve "RE1|RE2|..." – Regulární výrazy – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Ktorý RE sa použil pri alternatíve "RE1|RE2|..." – Regulární výrazy – Fórum – Programujte.comKtorý RE sa použil pri alternatíve "RE1|RE2|..." – Regulární výrazy – Fórum – Programujte.com

 

m->29+6
Super člen
17. 12. 2011   #1
-
0
-

Zdravím, nenašiel som fórum pre Perl tak píšem sem. Mám taký problém s regulárnymi výrazmi v Perli. Parsujem HTML kód nejakých webov a pri priechode postupne nahradzujem niektoré výrazy. RE, ktorým nahradzujem vyzerá takto:  

$keyword_pattern = lc('(?:'.join(')|(?:', keys(%{$replacements})).')');
$text =~ s/\b($keyword_pattern)\b/inject_word_into_replacement($1)/gie;

Funkcia, ktorá sa stará o náhradu vyzerá zhruba takto (vyhádzal som nepodstatné veci): 

sub inject_word_into_replacement {
  my ($self, $word) = @_;

  my $lower_cased_word = lc($word);

  my $replacement = $replacements{!!!Tu potrebujem zistiť vzor podľa kt. sa slovo našlo aby som ho mohol použiť ako kľúč!!!};
  $replacement =~ s/\{keyword\}/$word/;
  return $replacement;
}

No a v hashi $replacements mám uložené texty, ktoré sa majú za dané slovo nahradiť. Napríklad <abbr title="Operačný systém">{keyword}</abbr>, pričom kľúč pre to je reťazec OS. Takto mám v tom hashi plno slov.

Lenže ako kľúč používam aj slová ako HTTP\w?, Potom ak sa v texte nachádza reťazec HTTP alebo HTTPS tak skript spraví náhradu <abbr title="Hyper text...">{keyword}</abbr> a za {keyword} dosadí správne slovo.

Samozrejme som to zjednodušil, pretože opísať 2 krát to isté pre HTTP i HTTPS mi nevadí, no v praxi sú tam slová, ktoré ma ani nenapadnú a chcem len doplniť ich koniec pomocou \w* a priradiť im náhradu.

A otázka teda znie: Ako zistiť vo funkcii inject_word_into_replacement vzor podľa ktorého sa dané slovo našlo, aby som následne mohol ten vzor použiť ako kľúč k tomu hashu a získal tak správnu náhradu?


Nahlásit jako SPAM
IP: 83.240.51.–
KIIV
~ Moderátor
+43
God of flame
17. 12. 2011   #2
-
0
-

nejak te moc nechapu... pokud je $replacements hashref tak   $replacements->{$word}

samozrejme to predpoklada, ze mas vsechny klice v $replacements malejma pismenama, protoze jinak se bude blbe indexovat, kdyz je tam libovolne pismeno jinak velky -> tj. kdyz je sice zmensis do toho patternu na vyhledavani, ale nemas klice malejma, tak se to bude hledat blbe

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
m->29+6
Super člen
18. 12. 2011   #3
-
0
-

Som si myslel, že to nikto nepochopí a tak som pridával text a nepomohlo :-( Takže inak. Mám takýto hash: 

$replacements = {
  'dievčat\w*' => '<img src="girls.jpg" alt="{keyword}" />',
  'lacn\w* oblečen\w*' => '<a href="http://oblecenie.super-eshop.sk/">{keyword}</a>',
};

Ak spravím toto: 

$keyword_pattern = lc('(?:'.join(')|(?:', keys(%{$replacements})).')');
$text =~ s/\b($keyword_pattern)\b/inject_word_into_replacement($1)/gie;

Tak vlastne dostanem niečo takéto: 

$text =~ s/\b((?:dievčat\w*)|(?:lacn\w* oblečen\w*))\b/inject_word_into_replacement($1)/gie;

A a ak mám v premennej $text uložený napr. reťazec "Vďaka našim dievčatám sa nám podarilo vyhrať MS v ...". Potom to samozrejme nájde slovo dievčatám, ktoré budem mať vo funkcii prístupné ako premennú $word, no ja potrebujem vedieť, ktorý vzor tam tú premennú dostal, a teda reťazec "dievčat\w*". Pretože to je kľúč do toho hashu.

Dúfam, že teraz to pochopíš, lebo už neviem ako to vysvetliť.

Nahlásit jako SPAM
IP: 83.240.51.–
KIIV
~ Moderátor
+43
God of flame
18. 12. 2011   #4
-
0
-

tak v tomdle pripade me napada leda projet jednotlive klice proti tomu nalezenemu slovu... dokud nenarazis na shodu

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
m->29+6
Super člen
18. 12. 2011   #5
-
0
-

No to práve napadlo aj mňa, ale to parsovanie je celkom časovo kritické a tých slov je tam hrozne moc. Som len myslel, či neexistuje nejaký trik ako v Perle zistiť, ktorý RE matchol.

Už som pregooglil internet a nič schopného som nenašiel. Hoci som ani moc nevedel čo mám hľadať :-D

Nahlásit jako SPAM
IP: 83.240.51.–
KIIV
~ Moderátor
+43
God of flame
18. 12. 2011   #6
-
0
-

Funkcionalita, kterou pozadujes se neda udelat nejak snadno... jen tak z hlavy me napada jen par moznosti co se s tim da delat... jeden sem uz zminoval

druhy je vykonavat jednotlive regularni vyrazy samostatne... ale musel by si asi udelat benchmarky... (jestli je lepsi prvni nebo druhy)

treti nejbrutalnejsi - pouzit XS / Inline::C/CPP a naimplementovat neco jako binarni vyhledavani v tech regularnich vyrazech :D (nevylucuju ze by to pak mohlo chtit i upravy knihoven pro RE - nebo v horsim pripade i vlastni implementaci) :D - kazdopadne se da aspon prostudovat jestli to neumi predat nejaky info o matchi (ale pochybuju o tom)...

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
m->29+6
Super člen
18. 12. 2011   #7
-
0
-

Si mi dobre naložil :-D

 Ten 2. spôsob som mal implementovaný ako 1. variantu a dávalo mi to vyše 2 sekúnd oproti terajším okolo 100 milisekundám.

Ten 3. je až fakt asi posledná varianta, keby sa mi nepodarilo ľudí presvedčiť, že to proste nejde :-D

Takže teraz ma napadlo nejak odchytávať debug informácie a poskladať to z toho. To ale zase spomalí RE, tak uvidím ako to dopadne.

Každopádne dík za nápady, v Perli nerobím a toto je taká bokovka (dúfam) a o inline C/CPP som nevedel. Takže pri najhoršom si implementujem nejaký hash, ktorý vyhľadáva podľa prefixu. Kedysi som pri spracovaní prirodzeného jazyka používal Trie štruktúru tak hádam ju využijem znovu, alebo nejakú Trie pre Perl stiahnem :-) Na PCRE úpravu/implementáciu si fakt netrúfam.

Nahlásit jako SPAM
IP: 83.240.51.–
KIIV
~ Moderátor
+43
God of flame
18. 12. 2011   #8
-
0
-

mimochodem zkousel si taky pridat  ^ a $ ? mohlo by to aspon trosku zrychlit, pokud by nebyly skoro stejny vyrazy

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
m->29+6
Super člen
18. 12. 2011   #9
-
0
-

Kam pridať? A kde by boli rovnaké výrazy? Moc ti teraz nerozumiem. Ja potrebujem hľadať tie slová aj v strede textu, nie len na začiatku a konci.

Nahlásit jako SPAM
IP: 83.240.51.–
KIIV
~ Moderátor
+43
God of flame
18. 12. 2011   #10
-
0
-

prvni navrh ve funkci: inject_word_into_replacement

kdyz bys vyhledaval, ktery klic to naslo

je rozdil mit treba:    ^abcd\w+$  nad retezcem 'sssssssssssssssssssssssss'  -- hned na zacatku vi, ze to nezacina 'a'

ale kdyz mas   abcd\w+ tak RE musi projit stejne celej retezec protoze nevi jestli nahodou abcd\w+ neni nekde dal

(proste kdyz bys prochazel vsechny klice, ktery to naslo, tak takhle by to melo byt mirne rychlejsi)

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
m->29+6
Super člen
18. 12. 2011   #11
-
0
-

Jaj, jasné. To mám samozrejme všade kde porovnávam len na slovo.

Nahlásit jako SPAM
IP: 83.240.51.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 8 hostů

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý