[PHP] backreferences met preg_replace

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Skaah
  • Registratie: Juni 2001
  • Laatst online: 16-09 18:38
Ik gebruik de volgende functie om woorden in een string op een HTML-veilige manier te highlighten.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function highlight($keywords,$string)
{
        $styles = array('color: #fff; background-color: #909;',
                        'color: #000; background-color: #ff6;',
                        'color: #000; background-color: #aff;',
                        'color: #000; background-color: #9f9;',
                        'color: #000; background-color: #f99;',
                        'color: #000; background-color: #f6f;',
                        'color: #fff; background-color: #800;',
                        'color: #fff; background-color: #0a0;',
                        'color: #fff; background-color: #860;',
                        'color: #fff; background-color: #049;',
        );

        foreach($keywords as $keyword)
        {
                $style = next($styles);
                if (!$style)
                {
                        $style = reset($styles);
                }
                $string = preg_replace("/(>|^)([^<]+)(?=<|$)/esx",
                "'\\1'.preg_replace('!\b(".preg_quote($keyword).")\b!i','<span
 style=\"background-color: ".$style.";font-weight: bold;\">".$keyword."</span>','\\2')",
                                       $string);
        }
        return $string;
}


Zoals je ziet is de code vrij eenvoudig. Nu zit er één bugje in deze functie: wanneer er hoofdletters in de tekst in een wooord zitten dat gehighlight moet worden, gaan die verloren. Er komen dan gewoon kleine letters te staan. Dit is nogal storend bij het begin van zinnen, namen etc.

Het probleem zit 'm erin dat het me niet lukt om de backreferences van de binnenste preg_replace aan te spreken. \\1, de reference die ik zou moeten hebben, verwijst naar de buitenste preg_replace. Hoe pak ik toch de references van de binnenste?

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Zoals het er nu staat kan het toch sowieso nooit werken? Je concat de binnenste replace aan de buitenste, maar je sluit niet de string af. Probeer die functie buiten de string te halen dus: "blaat".preg_replace('','','')."blaat"

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Skaah
  • Registratie: Juni 2001
  • Laatst online: 16-09 18:38
NMe84 schreef op 09 juni 2004 @ 09:44:
Zoals het er nu staat kan het toch sowieso nooit werken? Je concat de binnenste replace aan de buitenste, maar je sluit niet de string af. Probeer die functie buiten de string te halen dus: "blaat".preg_replace('','','')."blaat"
Serieus, ik zweer je dat het werkt. Ik weet dat de code er wat vreemd uit ziet, maar het werkt echt. Het lijkt op dit voorbeeld in de php manual: preg_replace
[edit]
Ik heb het opgelost met een preg_replace_callback.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
$highlight_styles = array('color: #fff; background-color: #909;',
                        'color: #000; background-color: #ff6;',
                        'color: #000; background-color: #aff;',
                        'color: #000; background-color: #9f9;',
                        'color: #000; background-color: #f99;',
                        'color: #000; background-color: #f6f;',
                        'color: #fff; background-color: #800;',
                        'color: #fff; background-color: #0a0;',
                        'color: #fff; background-color: #860;',
                        'color: #fff; background-color: #049;',
);
$highlight_style = reset($highlight_styles);

function highlight($keywords,$string)
{
        global $highlight_styles, $highlight_style;
        foreach($keywords as $keyword)
        {
                $highlight_style = next($highlight_styles);
                if (!$highlight_style)
                {
                        $highlight_style = reset($highlight_styles);
                }
                $string = preg_replace("/(>|^)([^<]+)(?=<|$)/esx",
"'\\1'.preg_replace_callback('!\b(".preg_quote($keyword).")\b!i','highlight_callback','\\2')",
$string);
        }
        return $string;
}

function highlight_callback($matches)
{
        global $highlight_style;
        return '<span style="font-weight: bold; '.$highlight_style.'">'.$matches[1].'</span>';
}

[ Voor 78% gewijzigd door Skaah op 09-06-2004 11:23 ]


Acties:
  • 0 Henk 'm!

  • WormLord
  • Registratie: September 2003
  • Laatst online: 10:10

WormLord

Devver

Met de volgende replace lukt het ook.
PHP:
1
2
3
4
5
6
<?
      $string = preg_replace("/(>|^)([^<]*)\b(".preg_quote($keyword).")\b([^<]*)(?=<|$)/isx",
                           "\\1\\2<span style=\"background-color: ".$style.
                           ";font-weight: bold;\">\\3</span>\\4\\5",
                           $string);
?>

Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

Lees mijn post in dat vorige topic dat hier over ging even door.

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz