Avatar billede pitzen Nybegynder
12. april 2010 - 09:09 Der er 10 kommentarer og
1 løsning

Regulært udtryk driller i preg_replace

Hej eksperter.


Jeg har følgende funktion, som fremhæver nogle bynavne i en string.

function highlightCities($text, $words)
{
    foreach ($words as $word)
    {
        $word = preg_quote($word);
        preg_match("/\b$word\b/", $text, $regs);
        if($regs[0] != "")
            $cities[] = $regs;

        $text = preg_replace('/\b('.$word.')\b/', '<span class="hightlight_city">\1</span>', $text);
    }
    $return['text'] = $text;
    $return['cities'] = $cities;
    return $return;
}


Problemet er bare, at udtrykket vil highlighte "borg" i "Søborg", da der findes en by ved navn Borg. Jeg vil gerne have det rettet til, så det kun matcher hele ord.

Er der nogle, der har et forslag til hvordan jeg kan finde det bynavn, som fremkommer flest gange i teksten?


Pf. tak :)
Avatar billede repox Seniormester
12. april 2010 - 10:01 #1
For at gengive dit scenarie, prøvede jeg med disse data:
$words = array("Borg", "Søborg", "Silkeborg");

$text = "Velkommen til Søborg hvor græsset altid er grønt!";

og i den sammenhæng virker din funktion fint.
Avatar billede Slettet bruger
12. april 2010 - 10:04 #2
Jeg lavede mit eget lille eksempel for at tjekke om det virkede, og det gjorde det sørme.. Så poster det lige her så kan du selv vælge hvad af det du vil bruge :-)

PHP Koden:
<?php
/**
* city_highlighter(string $text, array $cities)
* $text  : Text to perform highlight on
* $cities : Array of city names to highlight
* @return : $text with $cities highlighted.
*/
function city_highlighter($text, $cities)
{
    // Joining $cities into a REGEX-friendly string
    $cities = implode("|", $cities);
   
    // Creating regex pattern (case insensitive)
    $pattern = "/(\b" . $cities . "\b)/i";
   
    // Transform $cities into:
    $transform = '<b>\\1</b>';
   
    $output = preg_replace($pattern, $transform, $text);
   
    return $output;
}

$cities = "Aalborg, Aarhus, Århus, Odense, København";
$cities = explode(", ", $cities);
$text = "I Aalborg findes Gigantium, i Århus findes Musikhuset, i Odense har de hat og briller og i København har de Cirkusbygningen!";

echo '<b>Normal unformatted version of $text:</b><br>' . $text . '<br><br><b>City higlighted version of $text:</b><br>' . city_highlighter($text, $cities);
?>

Output/Resultat som HTML:
<b>Normal unformatted version of $text:</b><br>
I Aalborg findes Gigantium, i Århus findes Musikhuset, i Odense har de hat og briller og i København har de Cirkusbygningen!<br><br>

<b>City higlighted version of $text:</b><br>
I <b>Aalborg</b> findes Gigantium, i <b>Århus</b> findes Musikhuset, i <b>Odense</b> har de hat og briller og i <b>København</b> har de Cirkusbygningen!


(Sorry til jer fra Odense og omegen, men kunne ikke lige finde på noget at skrive om jer ;-))
Avatar billede Slettet bruger
12. april 2010 - 10:05 #3
Ups, skal siges jeg aldrig prøvede din funktion af, gik direkte igang med min egen.
Avatar billede pitzen Nybegynder
12. april 2010 - 12:18 #4
roxki >> Jeg har et kæmpe array med byer og derfor virker din implode funktion ikke. Strengen bliver simpelthen for lang :)

repox >> Det har du ret i. Det var faktisk et andet eksempel jeg burde have givet. Der er en by ved navn "Ans", som f.eks. bliver fremhævet i "Ansøgning". Kan jeg undgå det?
Avatar billede repox Seniormester
12. april 2010 - 12:33 #5
Med disse testdata:
$words = array("Ans", "Arenborg", "Aalborg");

$text = "Ansøgning bedes sendt til Aalborg kommune!";


virker det også som det skal?
Avatar billede pitzen Nybegynder
12. april 2010 - 12:42 #6
Det gør den hos mig:
<span class="hightlight_city">Ans</span>øgning - sådan kommer du videre

Men dog ikke her senere i teskten:
benytte linket "send ansøgning".
Avatar billede Slettet bruger
12. april 2010 - 12:44 #7
Jeg har ændret min funktion så den tager én by af gangen, ligesom din gør, og testet den med en ny streng - hvilket gav mit ønskede resultat.

Min nye kode:
<?php
/**
* city_highlighter(string $text, array $cities)
* $text  : Text to perform highlight on
* $cities : Array of city names to highlight
* @return : $text with $cities highlighted.
*/
function city_highlighter($text, $cities)
{
    $output = $text;
    foreach($cities as $city)
    {
        // Creating regex pattern (case insensitive)
        $pattern = "/(\b" . $city . "\b)/";
       
        // Transform $cities into:
        $transform = '<b>\\1</b>';
       
        $output = preg_replace($pattern, $transform, $output);
    }
   
    return $output;
}

$cities = "Aalborg, Aarhus, Århus, Ans";
$cities = explode(", ", $cities);
$text = "I Aalborg findes Gigantium, i Århus findes Musikhuset, Ansøgninger bedes sendes til vores afdeling i Ans.";

echo '<b>Normal unformatted version of $text:</b><br>' . $text . '<br><br><b>City higlighted version of $text:</b><br>' . city_highlighter($text, $cities);
?>

Og resultatet:
<b>Normal unformatted version of $text:</b><br>
I Aalborg findes Gigantium, i Århus findes Musikhuset, Ansøgninger bedes sendes til vores afdeling i Ans.<br<br>

<b>City higlighted version of $text:</b><br>
I <b>Aalborg</b> findes Gigantium, i <b>Århus</b> findes Musikhuset, Ansøgninger bedes sendes til vores afdeling i <b>Ans</b>.

Den forskel der er på mit og dit script er at jeg har lagt mit word-boundary-tegn ind i parantesen, hvor din ligger udenfor - vil tro det er der "fejlen" ligger.
Avatar billede repox Seniormester
12. april 2010 - 12:46 #8
HVilken PHP version anvender du? For det virker fint hos mig; måske det er en bug i versionen...
Avatar billede pitzen Nybegynder
12. april 2010 - 13:07 #9
PHP Version 5.2.6-1+lenny6


Jeg har testet igen og "Ans" bliver kun highlighted hvis det er først i en sætning.

$return = highlightCities("Jeg bor i Søborg. Jeg søger en Ansat. Ansøgninger sendes.", array("Søborg","Ans"));
$text = $return['text'];
echo $text;

Jeg bor i <span class="hightlight_city">Søborg</span>. Jeg søger en Ansat. <span class="hightlight_city">Ans</span>øgninger sendes.
Avatar billede repox Seniormester
12. april 2010 - 13:29 #10
Jeg kan ikke sige andet end at en direkte, umodificeret kopi af din funktion virker fint hos mig.
Jeg bruger PHP 5.3.2
Avatar billede pitzen Nybegynder
29. juni 2010 - 18:36 #11
fandt desværre aldrig en løsning. lukker
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester