[PHP/Regex] Dubbelquote

Pagina: 1
Acties:
  • 107 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • BlackWhizz
  • Registratie: September 2004
  • Laatst online: 08-12-2024
Hey

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function validate($text)
{
    $text = htmlspecialchars($text);
    $text = nl2br($text);
    
    $text = preg_replace( '/\[b\](.+?)\[\/b\]/is', '<b>\\1</b>', $text );
    $text = preg_replace( '/\[i\](.+?)\[\/i\]/is', '<i>\\1</i>', $text );
    $text = preg_replace( '/\[u\](.+?)\[\/u\]/is', '<u>\\1</u>', $text );
    $text = preg_replace( '/\[center\](.+?)\[\/center\]/is', '<center>\\1</center>', $text );
    $text = preg_replace( '/\[color=(.+?)\](.+?)\[\/color\]/is', '<span style="color: \\1;">\\2</span>', $text );
    $text = preg_replace( '/\[url=(.+?)\](.+?)\[\/url\]/is', '<a href="\\1">\\2</a>', $text );
    $text = preg_replace( '/\[url\](.+?)\[\/url\]/is', '<a href="\\1">\\1</a>', $text );
    $text = preg_replace( '/\[img\](.+?)\[\/img\]/is', '<img src="\\1" />', $text );
    $text = preg_replace( '/\[quote\](.+?)\[\/quote\]/is', '<blockquote><strong>Citaat:</strong><br />\\1</blockquote>', $text );
    $text = preg_replace( '/\[quote=(.+?)\](.+?)\[\/quote\]/is', '<blockquote><strong>Citaat van \\1:</strong><br />\\2</blockquote>', $text );
    $text = preg_replace( '/\[offtopic\](.+?)\[\/offtopic\]/is', '<span style="font-size: 10px; color: gray;"><em>Offtopic:<br />\\1</em></span>', $text );
    $text = preg_replace( '/\[off\](.+?)\[\/off\]/is', '<span style="font-size: 10px; color: gray;"><em>Offtopic:<br />\\1</em></span>', $text );
    
    return $text;
}


Werkt allemaal heel fijn. Maar nu wil ik als je een quote in een quote hebt dat de quote wordt veranderd in [..].

Omdat ik veel te weinig ervaring heb met Regex, ik heb geluk dat ik dit kon vinden op Wmcity vraag ik het aan jullie. Ik heb gegoogled. Maar dan krijg je allemaal uitleg over Invision Power board enz.

Groetjes
Koen

Acties:
  • 0 Henk 'm!

  • kokx
  • Registratie: Augustus 2006
  • Laatst online: 13-09 20:30

kokx

WIN

Met een regex-based ubb parser is dit heel moeilijk om te realiseren. Je zou beter kunnen kijken naar stack-based ubb parser, waarbij je veel betere controle over de context hebt en je dus quotes veel makkelijker kunt nesten.

Acties:
  • 0 Henk 'm!

  • BlackWhizz
  • Registratie: September 2004
  • Laatst online: 08-12-2024
Ikk kan weinig vinden over stack-based parsen. Kan iemand mij functies daarvoor geven/eventueel kleine uitleg?

Acties:
  • 0 Henk 'm!

Verwijderd

Soms is 't handiger om niet zelf het wiel weer uit te vinden, dus kijk hier 's: http://pear.php.net/package/HTML_BBCodeParser

Kleine uitleg: bij een stack based parser kieper je niet een stuk of 15 rules (de regexen in jouw voorbeeld) over een tekst, maar loop je tekst zelf langs van begin tot eind.
Op 't moment dat je een begintag tegenkomt ([b] bijvoorbeeld) zet je die op de stack (al dan niet tokenized) en ga je op zoek naar de bijbehorende eindtag ([/b]). Op 't moment dat je die eindtag tegenkomt, verwerk je die tussenliggende tekst (in dit geval bold maken) en haal je die begintag entry weer van de stack.
Wanneer je binnen die [b] bv een [i] tag tegenkomt weet je dat je een tag binnen een tag hebt, maar in feite hoef je daar niet moeilijk over doen: tag op de stack plaatsen, zoeken naar de eindtag en de tussenliggende tekst italic maken. Die [b] tag op de stack zorgt er wel voor dat dat italic stuk ook bold blijft.

In jouw geval (quote binnen een quote) kun je kijken of de vorige tag op de stack ook al een quote tag was, zo ja, dan vervang je de tussenliggende tekst door '[...]'.

Maar eigenlijk hoor je wanneer je geen geneste quotes wil hebben die originele quotes al door '[...]' te vervangen voordat 'ie wordt aangeboden aan de gebruiker die een reply wil intikken. Dan heb je bij het verwerken van die reply al geen geneste quotes meer.

En verkijk je niet op het schrijven van een stack based parser: om die 15 regexen te vervangen kom je al gauw op een paar honderd regels code. En dan nog kan 'ie niet overweg met fouten als "[b][i]hallo[/b][/i]" (die italic endtag had binnen de bold endtag moeten zitten). Wil je dat ook nog goed afvangen, reken dan nog op een substantieel aantal regels extra code.

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:44

crisp

Devver

Pixelated

Het kan overigens wel met een reguliere expressie; PCRE ondersteund immers recursie. Dan krijg je zoiets:
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
function quote($content)
{
    $re = '/\[quote(=([^\]]+))?\]((([^\[]*|\[(?!\/?quote))*|(?R))*)\[\/quote\]/i';

    if (is_array($content))
    {
        $quote = $content[3];

        // geneste quotes vervangen door [...]
        $quote = preg_replace($re, '<br />[...]<br />', $quote);

        // vervang [img]-tags door link naar afbeelding
        $quote = preg_replace(
                '/\[img\](http:\/\/)?(.*?)\[\/img\]/i',
                '<a href="http://$2">afbeelding</a>',
                $quote
        );

        return '<blockquote><strong>Citaat'
            . ($content[2] ? ' van ' . $content[2] : '')
            . ':</strong><br />' . trim($quote) . '</blockquote>';
    }
    else
    {
        return preg_replace_callback($re, 'quote', $content);
    }
}

:)

Intentionally left blank


Acties:
  • 0 Henk 'm!

Verwijderd

Met die recursie ben je natuurlijk ook al stack based bezig, alleen laat je 't dan over aan PHP/PCRE. Ik wist overigens niet dat PCRE dat kon (ben geen PHP'er).
Maar met die constructie ben je ook al gauw een paar honderd regels verder i.p.v. 11 regexen van TS. Ik ga dan eerder voor een oplossing die ook nog leesbaar is... ;)

(C# heeft de optie om een '@' voor een string te zetten om aan te geven dat alle karakters in die string literal zijn en niet ge-escaped hoeven te worden. lijkt me een ideale toevoeging in PHP, zeker bij ingewikkelde regexen...)

Acties:
  • 0 Henk 'm!

  • BlackWhizz
  • Registratie: September 2004
  • Laatst online: 08-12-2024
Bedankt voor de informatie, mijn probleem is opgelost, dit had ik snel nodig dus de functie van crisp lijkt mij nu de handigste oplossing. Ik ga binnenkort bezig met een stack-based-parser.
Pagina: 1