RegExp und preg_match()

DEATHNET

Lieutnant
Mitglied seit
05.02.2007
Beiträge
75
Renomée
0
Dieser Test führt zu gewolltem Ergebis:
PHP:
<?php
function grepurl($url) {
 preg_match("/(https?|ftps?):\/\/([a-z0-9%&\/=\?~#,\.\-_]+)/i",$url,$matches);
 return $matches[0];
}
echo grepurl("<b>http://www.domain.ltd</b>");
?>
Code:
http://www.domain.ltd

Dieser Versuch gibt allerdings immer ein leeres Array zurück:
PHP:
function decodetext($text) {
 $text = preg_replace("/\[a\](.*)\[\/a\]/siU","<a href=\"".grepurl("\\1")."\" target=\"_blank\">\\1</a>",$text);
 return $text;
}

function grepurl($url) {
 preg_match("/(https?|ftps?):\/\/([a-z0-9%&\/=\?~#,\.\-_]+)/i",$url,$matches);
 return $matches[0]; # return gibt leeres Array zurück obwohl der String ordnungsgemäß übergeben wird!
}

ein Test mit Pattern:
PHP:
"/(.*)/"
gibt:
Code:
<b>http://www.domain.ltd</b>
zurück!


Hab' ich hier irgendwo einen Denkfehler oder irgendwas übersehen?
 
Ja, du hast was übersehen. Und zwar, wenn der Parser deinen Programmcode auswertet, geht er von innen nach außen.

Das heißt, er packt \\1 in die Funktion grepurl hinein und setzt das Ergebnis in den String der decodetext() übergeben wird. Im Endeffekt hast du also, unabhängig davon, was Text enthält, immer folgendes in deinem Code stehen:

grepurl("\\1") evaluiert zu ""

womit die Funktion enthält
Code:
 $text = preg_replace("/\[a\](.*)\[\/a\]/siU","<a href=\"\" target=\"_blank\">\\1</a>",$text);


Was du willst ist "preg replace with eval", das heißt der e Modifier. Ohne Gewähr auf Richtigkeit:

Code:
function grepurl($url) { 
 preg_match("/(https?|ftps?):\/\/([a-z0-9%&\/=\?~#,\.\-_]+)/i",$url,$matches); 
 return $matches[0]; 
} 

function bbcode_link($url) {
 return "<a href=\"".grepurl($url)."\" target=\"_blank\">".$url."</a>";
}

function decodetext($text) { 
 $text = preg_replace("/\[a\](.*)\[\/a\]/siUe","bbcode_link(\\1)",$text);
 return $text; 
}

Dadurch dass hier der Funktionsname im String drin steht, wird er erst zur Laufzeit geparst und nicht vorher. preg_replace setzt dann auch schon den richtigen Wert für \\1 ein.
Evtl. stimmen die anderen Modifier nicht, k.A., bin grad zu faul die alle nachzugucken.
 
ich glaube jetzt hab' ich es doch geschafft:
PHP:
function decodetext($text) {
 $text = preg_replace("/\[a\](.*)\[\/a\]/esiU","grepurl('\\1')",$text);
 return $text;
}

function grepurl($url) {
 $title = $url;
 preg_match("/(https?|ftps?):\/\/([a-z0-9%&\/=\?~#,\.\-_]+)/i",$url,$matches);
 return "<a href=\"".$matches[0]."\" target=\"_blank\">".$title."</a>";
}

<!-- Kommentar zu meinem /e-Modifikator-Problem -->
das mit dem /e-Modifikator ist mir auch schon in den Sinn gekommen, aber wenn ich diesen angebe dann bekomme ich einen wunderschönen stderr serviert:
Code:
[Sat Sep 08 08:25:32 2012] [warn] [client 79.208.250.32] mod_fcgid: stderr: PHP Parse error:  syntax error, unexpected '<' in /pub/www/diablo.gamers-planet.de/htdocs/lib/functions.php(38) : regexp code on line 1
[Sat Sep 08 08:25:32 2012] [warn] [client 79.208.250.32] mod_fcgid: stderr: PHP Fatal error:  preg_replace(): Failed evaluating code: 
[Sat Sep 08 08:25:32 2012] [warn] [client 79.208.250.32] mod_fcgid: stderr: <a href="0" target="_blank">[b]http://diablo.gamers-planet.de[/b]</a> in /pub/www/diablo.gamers-planet.de/htdocs/lib/functions.php on line 38

PHP:
$text = preg_replace("/\[a\](.*)\[\/a\]/esiU","<a href=\"".grepurl("\\1")."\" target=\"_blank\">\\1</a>",$text);
 
Zuletzt bearbeitet:
das mit dem /e-Modifikator ist mir auch schon in den Sinn gekommen, aber wenn ich diesen angebe dann bekomme ich einen wunderschönen stderr serviert:
Weil der e-Modifikator besagt, dass die "Ersetzung" kein normaler String ist, sondern der Rückgabewert des im String stehenden Funktionsaufrufs.
 
soweit hab ich das schon überrissen ;)

allerdings stell ich mir nach wie vor die frage warum bei angegebenen Pattern:
PHP:
"/(.*)/"
Code:
<b>http://www.domain.ltd</b>
zurück gegeben wird und nicht nur die gefilterte domain...
 
Warum sollte er was anderes zurückliefern? "." matcht jedes Zeichen, also nimmt er alles was er kriegen kann. Der reguläre Ausdruck sollte also den kompletten String speichern, den du reingibst.

Gruß,
Max
 
Warum sollte er was anderes zurückliefern? "." matcht jedes Zeichen, also nimmt er alles was er kriegen kann. Der reguläre Ausdruck sollte also den kompletten String speichern, den du reingibst.

Gruß,
Max

das ist mir schon klar. drum wundere ich mich ja warum er den string dann nicht filtert wenn ich einen pattern angebe sondern NULL zurückgibt. siehe auch den anfangspost...
 
scheinbar versteht ihr meine Denkweise nicht ;)
aber egal, damit funktioniert es jedenfalls, warum auch immer:
PHP:
function decodetext($text) {
 $text = preg_replace("/\[a\](.*)\[\/a\]/esiU","makelink('\\1')",$text);
 $text = preg_replace("/\[a=(.*)\](.*)\[\/a\]/esiU","makelink('\\1','\\2')",$text);
 $text = preg_replace("/\[b\](.*)\[\/b\]/siU","<b>\\1</b>",$text);
 $text = preg_replace("/\[i\](.*)\[\/i\]/siU","<i>\\1</i>",$text);
 $text = preg_replace("/\[u\](.*)\[\/u\]/siU","<u>\\1</u>",$text);
 $text = nl2br($text);
 return $text;
}

function makelink($url,$title = "") {
 if (empty($title)) $title = $url;
 if (strlen($title) > 50) $title = substr($title,0,25)."...".substr($title,-25);
 preg_match("/(https?|ftps?):\/\/[^ \[\]<>]+/i",$url,$matches);
 return "<a href=\"".$matches[0]."\" target=\"_blank\" rel=\"nofollow\">".$title."</a>";
}

p.s. danke trotzdem für die hilfestellung!
 
könnte auch daran liegen das ihr schon wisst warum es nur so funktionieren kann ;)
ich hingegen muss (und will) es noch lernen und frage mich daher warum es nur so funktioniert, und nicht anders...
 
Zurück
Oben Unten