preg_replace vs. preg_match_all | Ersetzungsproblem

preg_replace vs. preg_match_all | Ersetzungsproblem

am 24.10.2006 19:18:52 von Andreas Otto

Servus zusammen,
mit folgendem Problem schlage ich mich gerade herum: Wir füttern ein
templatebasiertes CMS mit BBCode-artiger Formatierung. Da Linebreaks
per nl2br() umgesetzt werden, muss natürlich drauf geachtet werden,
dass diese Umsetzung so erfolgt, dass valider Code dabei herauskommt.

Lange Rede, kurzer Sinn: vor dem nl2br() sollen z.B. zwischen und
alle Zeichen entfernt werden, die dort nichts zu suchen haben.

Folgendes RegEx-Pattern verwende ich:
'#(<(/th|/td|/tr|tr|table)[^>]*>)([^<]*)(
$cnt enthält den bereits in HTML umgeformten Content.

Beispiel a) funktioniert:
if(preg_match_all('#(<(/th|/td|/tr|tr|table)[^>]*>)([^<]+)( $cnt, $r))
foreach(array_keys($r[0]) as $k)
$cnt =3D str_replace($r[0][$k], $r[1][$k].$r[4][$k], $cnt);

Beispiel b) funktioniert *nicht*:
$cnt =3D
preg_replace('#(<(/th|/td|/tr|tr|table)[^>]*>)([^<]*)( '\\1\\4', $cnt);

Hat irgendjemand eine Idee, warum das so ist?

Hoch die Tassen,
Andreas

Re: preg_replace vs. preg_match_all | Ersetzungsproblem

am 24.10.2006 22:01:27 von Ulf Kadner

Andreas Otto schrieb:

> Beispiel b) funktioniert *nicht*:
> $cnt =
> preg_replace('#(<(/th|/td|/tr|tr|table)[^>]*>)([^<]*)( > '\\1\\4', $cnt);
>
> Hat irgendjemand eine Idee, warum das so ist?

Ja, in Singlequotes wird die Backreference nicht escapt.

MfG, Ulf

Re: preg_replace vs. preg_match_all | Ersetzungsproblem

am 25.10.2006 01:18:09 von Andreas Otto

Ulf Kadner schrieb:

> Ja, in Singlequotes wird die Backreference nicht escapt.

Doch, wird sie...

echo preg_replace('#^(\d+)(.*)$#', '\\2\\1', '12bla');

=> bla12

q.e.d. :)

Andreas

Re: preg_replace vs. preg_match_all | Ersetzungsproblem

am 25.10.2006 10:36:21 von Ulf Kadner

Andreas Otto schrieb:

>> Ja, in Singlequotes wird die Backreference nicht escapt.
>
> Doch, wird sie...
>
> echo preg_replace('#^(\d+)(.*)$#', '\\2\\1', '12bla');

Schau doch bitte ins Manual bevor Du versuchst ein Gegenargument zu
finden! Es ist so wie ich schrieb.

MfG, Ulf

Re: preg_replace vs. preg_match_all | Ersetzungsproblem

am 25.10.2006 11:27:12 von Andreas Otto

Ulf Kadner schrieb:

> Andreas Otto schrieb:
> > echo preg_replace('#^(\d+)(.*)$#', '\\2\\1', '12bla');
>
> Schau doch bitte ins Manual bevor Du versuchst ein Gegenargument zu
> finden!

Ich *versuche* nicht ein Gegenargument zu finden, ich habe Dir nur
gezeigt, dass auch in single quotes escapte back references problemlos
aufgelöst werden.
Ob escaped oder nicht - die Problematik bleibt die gleiche: die
Ersetzungen werden nicht durchgeführt. Nein, es wird auch nicht
"irgend ein scheiß" zurückgegeben - die Ersetzungen finden einfach
nicht statt und $cnt bleibt so, wie es ist.

mfg'
Andreas

Re: preg_replace vs. preg_match_all | Ersetzungsproblem

am 25.10.2006 11:58:34 von Ulf Kadner

Andreas Otto schrieb:
> Ulf Kadner schrieb:
>> Schau doch bitte ins Manual bevor Du versuchst ein Gegenargument zu
>> finden!
>
> Ich *versuche* nicht ein Gegenargument zu finden, ich habe Dir nur
> gezeigt, dass auch in single quotes escapte back references problemlos
> aufgelöst werden.

:-) Aber besser wirds damit halt nicht! Was ich Dir damit sagen wollte
ist nur das der Backslash unnötig ist.

> Ob escaped oder nicht - die Problematik bleibt die gleiche

Das kann gut sein.

> Ersetzungen werden nicht durchgeführt. Nein, es wird auch nicht
> "irgend ein scheiß" zurückgegeben - die Ersetzungen finden einfach
> nicht statt und $cnt bleibt so, wie es ist.

Gib doch mal ein vollständiges nicht funktionierendes Beispiel.

Ich kann das was Du schreibst leider nicht nachvollziehen!

$html = << blah
muss wech
blub
HTML;
$p = '#(<(/th|/td|/tr|tr|table)[^>]*>)([^<]*)( $html = preg_replace($p,'\1\4',$html);
echo $html;

# Output ist wie erwartet:

blahblub

MfG, Ulf

Re: preg_replace vs. preg_match_all | Ersetzungsproblem

am 25.10.2006 12:33:39 von Andreas Otto

Ulf Kadner schrieb:
> :-) Aber besser wirds damit halt nicht! Was ich Dir damit sagen wollte
> ist nur das der Backslash unnötig ist.

Dankend zur Kenntnis genommen :)

> Gib doch mal ein vollständiges nicht funktionierendes Beispiel.
>
> Ich kann das was Du schreibst leider nicht nachvollziehen!

Here we go:
$cnt =3D <<



weg mit mir


foo bar
foo2 bar2

HTML;

echo
"V1:\n",preg_replace('#(<(/th|/td|/tr|tr|table)[^>]*>)([^<]*)( '\1\4', $cnt),"\n\n";

preg_match_all('#(<(/th|/td|/tr|tr|table)[^>]*>)([^<]+)( $cnt, $r);
foreach(array_keys($r[0]) as $k)
$cnt =3D str_replace($r[0][$k], $r[1][$k].$r[4][$k], $cnt);
echo "V2:\n$cnt\n";
?>

Output:
V1:
weg mit mir

foobar
foo2bar2


V2:
=
foobar
foo2bar2


--- CUT ---
Heute, mit frischen Energien und genügend Kaffee, ist mir das Problem
aufgefallen: die Pattern unterscheiden sich in einem Zeichen: ([^<]*)
vs. ([^<]+)
Ganz großes Gna, Asche auf mein Haupt und Narrenkappe drauf. :|

Re: preg_replace vs. preg_match_all | Ersetzungsproblem

am 25.10.2006 12:48:08 von Ulf Kadner

Andreas Otto schrieb:

> Heute, mit frischen Energien und genügend Kaffee, ist mir das Problem
> aufgefallen: die Pattern unterscheiden sich in einem Zeichen: ([^<]*)
> vs. ([^<]+)
> Ganz großes Gna, Asche auf mein Haupt und Narrenkappe drauf. :|

:-) War mir auch nicht aufgefallen. Was solls.

MfG, Ulf

Re: preg_replace vs. preg_match_all | Ersetzungsproblem

am 25.10.2006 12:50:43 von Andreas Otto

Nachtrag: das hat noch nicht alles ersetzt, hier jetzt aber eine
funktionierende Version:

$c = 1;
while($c)
$cnt =
preg_replace('#(<(/th|/td|/?tr|table)[^>]*>)([^<]+)( $cnt, -1, $c);
?>