Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: [PHP] Sijamuotojen korvaaminen

Sivun loppuun

Petja [25.04.2011 12:08:41]

#

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?

Macro [25.04.2011 12:16:17]

#

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.

Antti Laaksonen [25.04.2011 12:20:44]

#

Tulisiko nimenomaan sanan ensimmäisen esiintymiskerran muuttua linkiksi?

Petja [25.04.2011 12:23:38]

#

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ä.

Macro [25.04.2011 12:26:38]

#

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.

Antti Laaksonen [25.04.2011 12:36:38]

#

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.

Petja [25.04.2011 12:38:44]

#

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

Antti Laaksonen [25.04.2011 13:25:21]

#

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;
?>

Antti Laaksonen [25.04.2011 14:27:03]

#

Voitko näyttää esimerkin tapauksesta, jossa tuo ei toimi? Muuten syyn selvittäminen on minulle vaikeaa.

Petja [25.04.2011 14:32:51]

#

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?

Metabolix [25.04.2011 19:28:44]

#

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> &lt; 3 kuumaa <a href="sanasivu.php?sana=kissa">kissaa</a>.

Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta