Preg_replace - regular expressions matchen niet
Ben ik alweer met een nieuwe vraag over vervangen van teksten :-)
Deze keer is de vraag iets simpeler (denk ik).
Ik heb een paar regels geschreven om zelf gemaakte UBB codes (uit een database) weer om te zetten naar HTML.
Voor links gebruik ik het volgende:
<a title="Google hover" href="www.google.nl/">Klik hier</a>
wordt in mijn UBB;
(Ook werkt het als er geen title tag is, dan maakt hij van de begin UBB-tag gewoon )
Naar UBB gaat het al super goed, maar de andere kant op nog niet.
Ik gebruik daarin de volgende regels:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
<?php
// link met titel
$input_toHTML = preg_replace(
"#\[url=(.+?)\|(.+?)\](.+?)\[/url\]#is",
"<a title=\"\\2\" href=\"\\1\"\">\\3</a>",
$input_toHTML);
// link zonder titel
$input_toHTML = preg_replace(
"#\[url=(.+?)\](.+?)\[/url\]#is",
"<a 22 href=\"\\1\">\\2</a>",
$input_toHTML);
?>
// link met titel
$input_toHTML = preg_replace(
"#\[url=(.+?)\|(.+?)\](.+?)\[/url\]#is",
"<a title=\"\\2\" href=\"\\1\"\">\\3</a>",
$input_toHTML);
// link zonder titel
$input_toHTML = preg_replace(
"#\[url=(.+?)\](.+?)\[/url\]#is",
"<a 22 href=\"\\1\">\\2</a>",
$input_toHTML);
?>
Nu gaan gedeeltes goed. Maar ik heb het idee dat het pattern nog niet klopt.
Kan het zijn dat ik een 'het moet beginnen met' en een 'het moet eindigen met' ben vergeten?
Ik heb de regels deels van internet gehaald en gemodificeerd naar eigen inzicht. Grotendeels snap ik het nu zelf ook!
Wie kan mij hiermee helpen?
Alvast bedankt!
Mvg, Robert
EDIT: Code tussen juiste tags gezet, nu wel leesbaar... ^noob
Gewijzigd op 04/01/2012 23:44:24 door Robert N
Voor PHP code moet je <?php voor je code en ?> na je code plaatsen. Voor HTML en JS en CSS en andere code moet je [code] tags gebruiken.
Gewijzigd op 04/01/2012 23:17:15 door - SanThe -
Post aangepast, is nu wel leesbaar.
Code (php)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
<?php
$regex = "#\[url=(.*)\/\|{0,1}(.*?)\](.*)\[/url\]#is";
$replace = "<a title=\"\\2\" href=\"\\1\">\\3</a>";
$input_toHTML = '[url=www.google.nl/|Google hover]Klik hier[/url]';
echo htmlentities(preg_replace($regex, $replace, $input_toHTML));
echo '<br />';
$input_toHTML = '[url=www.google.nl/]Klik hier[/url]';
echo htmlentities(preg_replace($regex, $replace, $input_toHTML));
?>
$regex = "#\[url=(.*)\/\|{0,1}(.*?)\](.*)\[/url\]#is";
$replace = "<a title=\"\\2\" href=\"\\1\">\\3</a>";
$input_toHTML = '[url=www.google.nl/|Google hover]Klik hier[/url]';
echo htmlentities(preg_replace($regex, $replace, $input_toHTML));
echo '<br />';
$input_toHTML = '[url=www.google.nl/]Klik hier[/url]';
echo htmlentities(preg_replace($regex, $replace, $input_toHTML));
?>
Voor beiden dezelfde regex geeft dit aan output:
<a title="Google hover" href="www.google.nl">Klik hier</a>
<a title="" href="www.google.nl">Klik hier</a>
Er zijn een aantal stappen die worden gedaan;
1. Dit is de tekst die in de database staat:
Code (php)
1
2
3
4
5
2
3
4
5
[p][url=http://www.google.nl]Externe link 1[/url][/p]
[p][url=http://www.phphulp.nl|Goede website]Externe link 2[/url][/p]
[p][url=/systemen]Interne link 1[/url][/p]
[p][url=/systemen/link2|linktekst]Interne link 2[/url][/p]
[p]Groetjes, Test-Kees[/p]
[p][url=http://www.phphulp.nl|Goede website]Externe link 2[/url][/p]
[p][url=/systemen]Interne link 1[/url][/p]
[p][url=/systemen/link2|linktekst]Interne link 2[/url][/p]
[p]Groetjes, Test-Kees[/p]
2. Op de nieuwspagina pagina wordt de tekst op deze manier geconverteerd:
Code (php)
1
2
3
4
2
3
4
<?php
include 'tekstconversie.php';
$converted_inhoud = conversie_toHTML($row->inhoud);
?>
include 'tekstconversie.php';
$converted_inhoud = conversie_toHTML($row->inhoud);
?>
3. In tekstconversie.php staat nu (o.a.) het volgende:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<?php
function conversie_toHTML($input_toHTML) {
$regex = "#\[url=(.*)\/\|{0,1}(.*?)\](.*)\[/url\]#is";
$replace = "<a title=\"\\2\" href=\"\\1\">\\3</a>";
$input_toHTML = preg_replace($regex, $replace, $input_toHTML);
// input retourneren
return $input_toHTML;
}
?>
function conversie_toHTML($input_toHTML) {
$regex = "#\[url=(.*)\/\|{0,1}(.*?)\](.*)\[/url\]#is";
$replace = "<a title=\"\\2\" href=\"\\1\">\\3</a>";
$input_toHTML = preg_replace($regex, $replace, $input_toHTML);
// input retourneren
return $input_toHTML;
}
?>
4. Verderop wordt dit alsvolgt gewoon ge-echo'd op het scherm:
Maar het resultaat in HTML is toch dit:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<p><a title="link2|linktekst" href="http://www.google.nl]Externe link 1[/url]</p>
<p>[url=http://www.phphulp.nl|Goede website]Externe link 2[/url]</p>
<p>[url=/systemen]Interne link 1[/url]</p>
<p>=/systemen">Interne link 2</a></p>
<p>Groetjes, Test-Kees</p>
<p>[url=http://www.phphulp.nl|Goede website]Externe link 2[/url]</p>
<p>[url=/systemen]Interne link 1[/url]</p>
<p>=/systemen">Interne link 2</a></p>
<p>Groetjes, Test-Kees</p>
Wat doe ik nog verkeerd?
Het lijkt alsof de regex maar een klein gedeelte vervangt en niet de hele expressie gebruikt. Maar waar gaat het nu fout?
Gewijzigd op 05/01/2012 19:41:38 door Robert N
Je geeft nu een compleet andere input. Dat is een heel ander verhaal. Hier zal je toch even moeten wachten op een echte regex-expert.
Of moet ik een nieuw topic maken maar dan niet in 'Beginnen met PHP'?
Mvg,
Robert
Gewijzigd op 06/01/2012 11:46:38 door B a s
Die (.*) is greedy, dus alles tussen het begin van de eerste open-tag en einde van de laatste open-tag zal als url gezien worden.
Ook in dat laatste deel, de tekst van de url. Daar kan je .+? gebruiken wat hetzelfde doet als .*, maar dan non-greedy, oftewel die probeert zo weinig karakters als maar mogelijk is te matchen.
Verder gaat die {0,1} (wat je kan schrijven als ?) niet helemaal goed. Zo wel:
Want (?:xxx)? betekent "match sub-patroon xxx 0 of 1 keer" en xxx is een pipe gevolgd door tekst (weer non-greedy).
Let wel op dat ik nu nog steeds andere dingen dan urls in je tag kan doen waardoor je site er niet veiliger op wordt.
Dat zou je nog kunnen afvangen door je patroon voor urls strikter te maken zodat het alleen echte urls matcht en dit soort dingen niet omzet. Of je maakt gebruik van preg_replace_callback en haalt htmlentities over de url en teksten heen.
Ik heb nu het volgende:
Code (php)
1
2
3
4
5
2
3
4
5
<?php
$regex = "#\[url=(.+?)(?:\|(.+?))?\](.+?)\[/url\]#is";
$replace = "<a title=\"\\2\" href=\"\\1\">\\3</a>";
$input_toHTML = preg_replace($regex, $replace, $input_toHTML);
?>
$regex = "#\[url=(.+?)(?:\|(.+?))?\](.+?)\[/url\]#is";
$replace = "<a title=\"\\2\" href=\"\\1\">\\3</a>";
$input_toHTML = preg_replace($regex, $replace, $input_toHTML);
?>
En het werkt helemaal!
Nog wel een vraagje, wil er natuurlijk wel van leren :-)
Wat is het verschil tussen de (.*) die ik gebruikte, en de (.+?) in het goede script?
Ik snap het 'greedy' nog niet helemaal, kun je een voorbeeldje geven?
Dit is een klein stukje van het script.
De $input_toHTML gaat nog door heel veel andere str_replace heen, o.a. < en > worden weggehaald.
In het begin nog een htmlentries is nog wel een goed idee ja.
Bedankt!
Gewijzigd op 06/01/2012 19:26:15 door Robert N