Tarkoitus olisi korvata tekstistä suomen kielen sijamuotoja.
function korvaa($nom,$gen,$part,$ess,$trans,$iness, $illat,$adess,$ablat,$allat,$abess, $komitat,$ins,$lnk,$txt) { $pos = strpos($txt,$nom); if($pos === true) { $txt=str_replace($nom,"<a href=\"{$lnk}\">{$nom}</a>",$txt); break 2; } }
En ole ajatellut vielä tehdä kaikkia sijamuotoja tuonne, koska en tiedä miten skripti käytännössä toimii. Tavoitteeni olisi, että skripti korjaisi tekstin
Matti käveli taloni ohi koirineen. Matilla on kuusi koiraa.
muotoon
Matti käveli taloni ohi koirineen. Matilla on kuusi koiraa.
Eli tekstistä korvataan sana koira vain yhden kerran. Sana voi olla missä tahansa sijamuodossa. Korvattu sana on linkki, joka määritetään funktion 14. variablessa $lnk
.
Tuntuu, että tästä ei tule mitään, joten auttaisiko joku edes vähän tämän kanssa. Tämän voi tehdä luultavasti myös säännöllisillä lausekkeilla. Selitinkö asiat nyt epäselvästi?
preg_replacella ainakin onnistuu.
preg_replace("/{$nom}/i", "<a href=\"{$lnk}\">{$nom}</a>", $txt, 1);
Lausekkeessa i
kertoo, ettei isojen ja pienten kirjaimien välille tehdä eroa.
Petja kirjoitti:
Selitinkö asiat nyt epäselvästi?
Olisi se ollut kyllä kivempi lukea ilman noita korostuksia.
Tulisiko nimenomaan sanan ensimmäisen esiintymiskerran muuttua linkiksi?
Macro kirjoitti:
preg_replacella ainakin onnistuu.
preg_replace("/{$nom}/i", "<a href=\"{$lnk}\">{$nom}</a>", $txt, 1);Lausekkeessa
i
kertoo, ettei isojen ja pienten kirjaimien välille tehdä eroa.
Tämän minä siis sujautan funktion sisään? Näitä strpos
juttuja ei tarvita? Minulla nämä säännölliset lausekkeet ovat ihan hepreaa.
Macro kirjoitti:
Petja kirjoitti:
Selitinkö asiat nyt epäselvästi?
Olisi se ollut kyllä kivempi lukea ilman noita korostuksia.
Sori, voin ottaa poiskin. Korostin nyt vain näitä avainsanoja.
Antti Laaksonen kirjoitti:
Tulisiko nimenomaan sanan ensimmäisen esiintymiskerran muuttua linkiksi?
Kyllä.
Esittämäni koodi hakee ensimmäisen esiintymisen, korvaa sen linkiksi ja jättää muut rauhaan. strpos-funktiota et tarvitse, koska preg_replacen neljäs parametri kertoo mitä korvataan.
Tässä on minun versioni:
<?php $sanat = "koira|koiraa|koiran|koirineen|koirassa|koiratta"; $linkki = "https://www.ohjelmointiputka.net/"; $teksti = "Matti käveli taloni ohi koirineen. Matilla on kuusi koiraa."; $teksti = preg_replace("/\b($sanat)\b/i", "<a href=\"$linkki\">\\0</a>", $teksti, 1); echo $teksti; ?>
Tässä muuttuja $sanat sisältää kaikki halutut taivutusmuodot.
Merkinnät \b varmistavat, että koodi korvaa vain kokonaisia sanoja.
Macron koodi:
Hmm... Ei tulosta haluttua tekstiä, ei myöskään mitään linkkejä, vaan sen sijasta tulostuksessa lukee $lnk
sisältö.
Antin koodi:
Höh! Ei toimi tämäkään.
Toteutukseni on seuraavanlainen:
function korvaa($nom,$gen,$part,$ess,$trans,$iness, $illat,$adess,$ablat,$allat,$abess, $komitat,$ins,$lnk,$txt) { $sanat = "{$nom}|{$gen}|{$part}|{$ess}|{$trans}|{$iness}|{$illat}|{$adess}|{$ablat}|{$allat}|{$abess}|{$komitat}|{$ins}"; $linkki = "https://www.ohjelmointiputka.net/"; $txt = preg_replace("/\b($sanat)\b/i", "<a href=\"$linkki\">\\0</a>", $txt, 1); return $txt; }
jonka jälkeen ajan funktion seuraavalla tavalla:
$lopputulos=korvaa("ohjelmointi"," .... "); //Lyhennetty
Kyllä tuo ainakin minulla toimii:
<?php function korvaa($nom,$gen,$part,$ess,$trans,$iness, $illat,$adess,$ablat,$allat,$abess, $komitat,$ins,$lnk,$txt) { $sanat = "{$nom}|{$gen}|{$part}|{$ess}|{$trans}|{$iness}|{$illat}|{$adess}|{$ablat}|{$allat}|{$abess}|{$komitat}|{$ins}"; $linkki = "https://www.ohjelmointiputka.net/"; $txt = preg_replace("/\b($sanat)\b/i", "<a href=\"$linkki\">\\0</a>", $txt, 1); return $txt; } $teksti = "Matti käveli taloni ohi koirineen. Matilla on kuusi koiraa."; $linkki = "https://www.ohjelmointiputka.net/"; $uusi = korvaa("koira", "koiran", "koiraa", "koirana", "koiraksi", "koirassa", "koiraan", "koiralla", "koiralta", "koiralle", "koiratta", "koirineen", "koirin", $linkki, $teksti); echo $uusi; ?>
Voitko näyttää esimerkin tapauksesta, jossa tuo ei toimi? Muuten syyn selvittäminen on minulle vaikeaa.
Jos kutsun useampaa korvaa-funktiota peräkkäin
$uusi=korvaa("koira" ... $uusi=korvaa("kissa" ... $uusi=korvaa("lehmä" ...
HTML-koodi menee sekaisin. Pätkii linkit omituisesti keskeltä, eikä sulje niitä asianmukaisesti. Sotkee myös jotkin linkit keskenään.
Tähän tyyliin:
<a href="http://ohjelmointiputka.net<a href="http://google.fi">">Google</a> ja <a href="http://google.fi/">Mureakuha</a>
Miten korjataan?
Voit koota kaikki vaihtoehdot yhteen lausekkeeseen ja tehdä korvauksen joko preg_replace_callback-funktion avulla erillisessä funktiossa tai preg_split-funktion avulla jälkikäteen silmukassa.
Lausekkeessa sanojen pitää olla sellaisessa järjestyksessä, että mikään myöhempi sana ei ala aiemmalla sanalla. Siis esimerkiksi sanat "kissa" ja "kissaa" pitää laittaa järjestykseen "kissaa|kissa", tai osumaksi tulee virheellisesti molemmissa tapauksissa pelkkä "kissa".
Jos on tarkoitus myös tuottaa turvallisesti HTML:ää, muista htmlspecialchars.
function korvaa_1($teksti) { $sanat = "kissaa|kissa|koirat|koira"; $lauseke = "/({$sanat})|(.+?(?={$sanat}|\$))/"; return preg_replace_callback($lauseke, "korvaa_1_callback", $teksti); } function korvaa_1_callback($osuma) { if (strlen($osuma[1])) { return linkki($osuma[1]); } return htmlspecialchars($osuma[0]); } function korvaa_2($teksti) { $sanat = "kissaa|kissa|koirat|koira"; $palat = preg_split("/({$sanat})/", $teksti, -1, PREG_SPLIT_DELIM_CAPTURE); $tulos = ""; foreach ($palat as $i => $pala) { if ($i % 2 == 0) { $tulos .= htmlspecialchars($pala); } else { $tulos .= linkki($pala); } } return $tulos; } function perusmuoto($sana) { switch ($sana) { case "kissaa": return "kissa"; case "koirat": return "koira"; } return $sana; } function linkki($sana) { return sprintf('<a href="sanasivu.php?sana=%s">%s</a>', urlencode(perusmuoto($sana)), htmlspecialchars($sana)); } $teksti = "Kaikki maailman koirat < 3 kuumaa kissaa.\n"; echo korvaa_1($teksti); echo korvaa_2($teksti); // Kaikki maailman <a href="sanasivu.php?sana=koira">koirat</a> < 3 kuumaa <a href="sanasivu.php?sana=kissa">kissaa</a>.
Aihe on jo aika vanha, joten et voi enää vastata siihen.