ugrás a tartalomhoz

RegEx csere stringen belül

vtsoftware · 2010. Szep. 19. (V), 18.15
Üdv mindenkinek...

Nem igazán értem még a RegEx működését, de szerintem csak evvel lehet megoldani amit szeretnék.

Adott egy adatbázis, benne cikkekkel.
Azonosító, cím, szöveg oszlopokkal - csak így egyszerűen.
Van egy másik adatbázis, ez egy nagy lista.
Szöveg, Tipp oszlopokkal.

A listában levő kulcsszavakat kellene a cikkekben lecserélnem.

Ezt most így valósítottam meg, de ez nagyon nem jó, sőt.
function replacer($str)
{
  $a=array();
  $b=array();
  $cmd=mysql_query("SELECT * FROM `tippek_tbl`");
  while ($row = mysql_fetch_array($cmd))
  {
    array_push($a, $row["keyword"]);
    array_push($b, "<span class=\"tooltip\" title=\"".strtoupper($row["keyword"]{0}).substr($row["keyword"], 1)."... ".$row["text"]."\">".$row["keyword"]."</span>");
  }
  return str_replace($a, $b, $str);
}
Először is kis-nagybetű érzékeny.
Azután pedig a cikkek szövegében BB-code IMG-taggel vannak megadva a képek.
Pl.: [IMG align=left id=cikkazonosito src=kepneve.jpg]
Így az a gond hogy ebben is lecseréli a kulcsszavakat.

Tehát, úgy kéne megoldani a kulcsszavak lecserélését, hogy kihagyja a BB Code tageket.

Milyen megoldást tudtok nekem mondani?
Előre is köszönöm a segítséget
 
1

Nem túl nehéz feladat

whiteman0524 · 2010. Szep. 19. (V), 18.47
Üdv !

Szerintem ezt a problémát úgy lehetne megoldani, hogy a bejövő szövegből egyenként "kivágod" az összes BBCode tagot, aminek nem szeretnéd hogy baja essen. Ezt úgy csinálod, hogy amikor találsz egy BBCode tagot, lecseréled egy egyedi azonosítóra (amit mondjuk generálsz). A lényeg hogy egyedi legyen, és tuti ne szerepeljen a listában, amiből majd cserélgeted a szavakat. Szóval mielőtt kicserélnéd az egyedi azonosítóra, kimented őket egy tömbbe például $tomb[$azonosito] => $tag formában. Ha mind megvan, akkor lefuttathatod a lecserélő algoritmusodat az immáron BBCode tagoktól mentes szövegen. Ez után pedig egyszerűen ismét végigmész az ideiglenes tömbödön, ahová a kulcsokat mentetted, és ha a szövegben találsz egy kulcsot, akkor azt lecseréled a megfelelő tag-ra, amit a kulcshoz társítottál anno.

Persze mindehhez regex kéne, de most idő hiányában csak ennyit tudtam mondani :) Hátha valaki leírja neked a konkrét példát :)
2

Nem is rossz gondolat...

vtsoftware · 2010. Szep. 19. (V), 19.04
Hmm, erre nem is gondoltam, nem rossz ötlet.
És most eszembe jutott egy Regex-mentes megoldás...
Végiggondolom, de attól jöhet mág tanács :)

Köszönöm szépen

Szerk.: Jut eszembe... evvel a BBCodekat megvédem, de hogy lehetne megoldani hogy a kis-nagy betűket ne vegye figyelembe?
3

preg_replace

SamY · 2010. Szep. 20. (H), 14.37
nem probaltam ki a lenti, de a regex elvileg jol futott teszt programban. Kis-/nagybetukre nem erzekeny.

function replacer($str) {  
    $cmd = mysql_query("SELECT * FROM `tippek_tbl`");  
    while ($row = mysql_fetch_array($cmd)) {  
        $str = preg_replace( 
            '/((\[[^\]]*\w+[^\]]*\]\s)*\s*)('.preg_quote($row['keyword']).')(\s*(\[[^\]]*\w+[^\]]*\])*)/ig', 
            '<span class="tooltip" title="' . ucfirst($row['keyword']) . '...' . $row["text"] . '">' . $row["keyword"] . '</span>',
            $str);  
        }  
    return $str;
}
4

A "g"...

vtsoftware · 2010. Szep. 20. (H), 16.23
Nagyon köszönöm, de sajnos nem működik.
Warning: preg_replace() [function.preg-replace]: Unknown modifier 'g' in FILE on line ###

Az i ha jól nézem (itt) a kis-nagy betű érzékenységet állítja.
A g nincs a listán és arra is hivatkozik. Néztem, kerestem (G00gle) mit tudok neki csinálni de nem találtam semmit...
5

a "g" modifier altalaban a

SamY · 2010. Szep. 21. (K), 09.36
a "g" modifier altalaban a globalis cseret jelezne (javascript eseten peldaul enelkul csak az elso talalatot csereli), PHP-ban viszont erre nincs szukseg, nyugodtan elhagyhatod.
6

Memória...

vtsoftware · 2010. Szep. 21. (K), 13.24
Így a memóriába szól bele.
Fatal error: Allowed memory size of 25165824 bytes exhausted (tried to allocate 12064875 bytes) in FILE on line ###
Ezt a preg_replace sorára írja.

Esetleg az milyen ötlet lenne ha megcsinálnám előre a BB-code "cserét" "whiteman0524" ötlete alapján, azután cserélném ki str_ireplace-vel a kulcsszavakat.
Vagy akkor inkább a regex? De az ini_set "memory_limit" nem működik, vagyis nem eredményes, akkor csak többet akar lefoglalni és ugyan ilyen hibaüzenetet kapok.

Megpróbálom összerakni "whiteman0524" ötletét... . . . vagy?
7

Az ötletemről

whiteman0524 · 2010. Szep. 21. (K), 16.17
Nem a leggyorsabb megoldás azt aláírom, mert tényleg meg lehetne oldani a problémát csupán regex használatával, mindenfajta tömbözés nélkül.

De talán van egy másik megoldás is, ami most jutott eszembe, és lehet hogy még a regex-nél is jobb. (de nem hiszem)

A lényege : Elindulnál a feldolgozandó szöveg elejéről, és addig mennél, amíg nem találnál egy BBCode tagot. Közben a megtalált karaktereket, vagy a szövegrészt valahogy mentenéd folyamatosan egy változóba. Nyilván ugye valamilyen módon az ilyen BBCode tagokat meg lehet különböztetni az egyéb szövegtől. Na most egyszerűen annyi lenne a teendő, hogy azon a szövegen ami még nem tartalmaz BBCode tagot - tehát amit kimentettél a változóba a tag előtt - máris lefuttathatnád a feldolgozó algoritmusodat, ami kicserélné benne az esetleges szavakat, az adatbázis listából. Ha megvan, akkor a tag után folytatod a keresést újabb tag után, és közben mented a szövegrészletet a változóba. Mindezt addig csinálod addig amíg el nem éred a szöveg végét.

Ennek a megoldásnak az az előnye, hogy az egész szövegen csupán egyszer kell végighaladni és egyből módosíthatod is. Ugyanakkor abból a szempontból lassabb lenne, hogy sok kis szövegrészletre kéne lefuttatnod a lecserélő algoritmusod, ami nyilván lassabb, mint ha egybe lerendeznéd az egész szöveget. De az megint egy plusz dolog, hogy mindössze egyetlen változóra lesz szükséged amit minden ciklusban felülírhatsz az aktuális szövegrészlettel :) Talán ehhez még regex-re sem lesz szükséged, legalábbis most így hirtelenjében azt hiszem.

Jah és az egész szövegfeldolgozó függvénynek ne felejtsd el referencia szerint átadni a feldolgozandó szöveget, hogy minél gyorsabban fusson az algoritmus. Persze ez nem a legszebb megoldás, mert ugye az eljárásokat nem komáljuk annyira, de mindenképpen gyorsabb lenne, mint ha a függvény-be belépve, az készítene a szövegről egy másolatot, és azon dolgozna.
8

Azt hiszem értem...

vtsoftware · 2010. Szep. 21. (K), 18.09
Azt hiszem tudom mire gondolsz...
Épp tegnap lettem kész egy PDF "készítővel" abban is kb. ez a módszer.
Íme
Ez is azt csinálja hogy ha <> taget talál, akkor melózik, különben pedig csak kiír...
9

Na hátha

vtsoftware · 2010. Szep. 21. (K), 20.27
Azt hiszem sikerült valami...

Evvel "eltűntetem" a BBCodekat miután HTML kóddá alakítottam őket.
$szavak=preg_replace("#<(.*?)>#sie", '"{{".base64_encode("$1")."}}"', $tx);
Evvel pedig kulcsszócsere után vissza:
$szavak=preg_replace("#{{(.*?)}}#sie", '"<".base64_decode("$1").">"', $tx);
Még nagyon az alap, de alakul.
Mint gondoltok?
10

Először is...

vtsoftware · 2010. Szep. 21. (K), 20.50
...elnézést a sok egymásutáni hsz-ért, de azt hiszem sikerült megoldanom.

Végülis a kulcsszócserélő ilyen lett, tökéletesen működik, úgy ahogy szerettem volna.
function replacer($str)
{
  global $MySQL;
  $str=preg_replace("#<(.*?)>#sie", '"{{".base64_encode("$1")."}}"', $str);
  $cmd=mysql_query("SELECT * FROM `tippek_tbl`");
  while ($row = mysql_fetch_array($cmd))
  {
    $str=preg_replace("#(".$row["keyword"].")#si", '<span class="tooltip" title="'.ucfirst($row['keyword']).'... - '.$row['text'].'">$1</span>', $str);
  }
  $str=preg_replace("#{{(.*?)}}#sie", '"<".base64_decode("$1").">"', $str);
  return $str;
}
Nos, akkor inkább azt kérdezném hogy erről mi a véleményetek.

Nagyon köszönöm a segítséget...