Regulärer Ausdruck
Horst
- php
Hallo!
Ich hab wiedermal ein Problem mit einem regulärem Ausruck und weiß keine Lösung.
Ich möchte alle Images der Form:
<img src="http://www.example.org/thumb.php?image_id=1234" alt="" />
ersetzen durch:
<a href="http://www.example.org/medium.php?image_id=1234">
<img src="http://www.example.org/thumb.php?image_id=1234" alt="">
</a>
Wobei die ID der Images beliebig lang sein kann. Es muss auch egal sein, ob es sich um einfache oder doppelte Anführungszeichen handelt.
Mein Versuch:
$str='<img src="http://www.example.org/thumb.php?image_id=1234" alt="" />';
$str=preg_replace('/\<img*thumb.php5\?image_id=(\d+)[\'|"]\s*\/>/i', '<a href="http://www.example.org/medium.php5?image_id=$1"><img src="http://www.example.org/thumb.php5?image_id=$1"></a>', $str);
Klappt aber leider nicht.
Kann mir jemand sagen, was ich da falsch mache?
mfg
Horst
Lieber Horst,
$str=preg_replace('/<img*thumb.php5?image_id=(\d+)['|"]\s*/>/i', ...
Was willst Du mit diesem ^^^^ Sternchen?
Wenn Du schon sowohl einfache als auch doppelte Anführungszeichen berücksichtigen möchtest, dann solltest Du auch explizit darauf prüfen! Was bringt es denn, wenn sich Dein Suchmuster mit einfachen Anführungszeichen am Anfang des src-Attributs, und mit doppelten am Schluss zufrieden gibt?
Mein Vorschlag (ungetestet!):
Nimm zunächst einmal die Tilde als Delimiter, dann muss man bei Pfaden nicht jeden Slash escapen. Die Tilde kommt so selten vor, dass man sie so gut wie nie escapen muss, was die Leserlichkeit enorm erhöt.
Wenn Du auf Backreferences eingehen möchtest, dann nimmst Du nicht $1, $2 usw. wie in Javascript, sondern \1, \2 usw.
Wenn Du schon Backreferences einsetzt, dann verwende sie doch auch dazu, um sicherzustellen, dass die umschließenden Anführungszeichen vorne wie hinten vom selben Typ (einfach oder eben doppelt, aber nicht beides zusammen) sind.
Diese Überlegungen bringen mich zu folgendem Code, wobei die erste Klammer die Art der Anführungszeichen speichert, die zweite die ID Deines Thumbnails:
$str = '<img src="http://www.example.org/thumb.php?image_id=1234" alt="" />';
$replaced_str = preg_replace(
'~(?is)<img [^>]*src=(["\'])[^"\']+thumb.php5\?image_id=(\d+)(\\1)[^>]*>~',
'<a href="http://www.example.org/medium.php5?image_id=\\2"><img src="http://www.example.org/thumb.php5?image_id=\\2" alt="" /></a>',
$str);
Liebe Grüße aus Ellwangen,
Felix Riesterer.
Hallo Felix,
Wenn Du auf Backreferences eingehen möchtest, dann nimmst Du nicht $1, $2 usw. wie in Javascript, sondern \1, \2 usw.
Wenn Du Referenzen verwenden möchtest - was hier sehr sinnvoll ist - dann nimmst Du bereits seit Jahren bevorzugt $1, $2 usw. und nicht \1, \2, usw, siehe Handbuch.
Wenn Du schon Backreferences einsetzt, dann verwende sie doch auch dazu, um sicherzustellen, dass die umschließenden Anführungszeichen vorne wie hinten vom selben Typ (einfach oder eben doppelt, aber nicht beides zusammen) sind.
Diese Überlegung erscheint mir wenig schlüssig. Wenn die Anführungszeichen nicht paarweise sind, dann liegt ungültiges HTML (oder was auch immer) vor. Es ist keine Rede davon, dass damit ungültiger Kram gültig gemacht werden soll, sondern eher, dass funktionierender alter Code in funktionierenden neuen Code verarbeitet werden soll. Das heißt natürlich nicht, dass man hier nicht eine Referenz einsetzen kann.
[^>]*src=(["'])[^"']+thumb.php5?image_id=(\d+)(\1)[^>]*>~',
Könntest Du mir den * (fast am Ende) in diesem Teilmuster erläutern, erfasst Du damit ggf. nicht viel zu viel (Gier)? Ja, es klappt mit der Beispielzeichenkette (oder auch nicht wegen php5), aber nicht mit einer ganzen Datei.
Das Alt-Attribut lässt sich wunderbar mit einer Referenz einfangen, das ist meiner Meinung nach sinnvoller als eine Referenz für die Anführungszeichen (einigen wir uns auf insgesamt drei Referenzen ;-)).
Freundliche Grüße
Vinzenz
Hallo Horst,
ich versuche Deine Beschreibung und Deinen Ansatz, die sich zum Teil widersprechen, unter einen Hut zu bringen.
Ich möchte alle Images der Form:
<img src="http://www.example.org/thumb.php?image_id=1234" alt="" />
ersetzen durch:
<a href="http://www.example.org/medium.php?image_id=1234">
<img src="http://www.example.org/thumb.php?image_id=1234" alt="">
</a>
Wobei die ID der Images beliebig lang sein kann. Es muss auch egal sein, ob es sich um einfache oder doppelte Anführungszeichen handelt.
Mein Versuch:
$str='<img src="http://www.example.org/thumb.php?image_id=1234" alt="" />';
$str=preg_replace('/<imgthumb.php5?image_id=(\d+)['|"]\s/>/i', '<a href="http://www.example.org/medium.php5?image_id=$1"><img src="http://www.example.org/thumb.php5?image_id=$1"></a>', $str);
>
> Klappt aber leider nicht.
"Klappt nicht" ist keine Fehlerbeschreibung - allerdings bedeutet dies in Deinem Fall, dass keine Ersetzung vorgenommen wird.
Dein Suchmuster lautet
'/\<img\*thumb.php5\?image\_id=(\d+)[\'|"]\s\*\/>/i'
Reguläre Ausdrücke sind sicher nicht meine Stärke, aber mit Hilfe des Abschnittes [Reguläre Ausdrücke](http://de.selfhtml.org/perl/sprache/regexpr.htm) des Perlkapitels von SELFHTML habe ich das hinbekommen.
1\. Fehler: Das Zeichen "<" ist kein Zeichen mit Sonderbedeutung, also muss es nicht maskiert werden.
2\. Fehler:
Hinter "img" verwendest Du "\*". Du erwartest also eine Folge von beliebig vielen (auch kein) "g" bis irgendwann "thumb" folgt. Die Zeichenkette dort wirfst Du übrigens unbeachtet weg, ich nehme einfach an, dass es sich um das Protokoll und die Domain handelt, die sich nicht ändern. In Wirklichkeit erwartest Du doch wohl eher ein
src=
gefolgt von einem einfachen oder doppelten Anführungszeichen. Dazu später
3\. Fehler:
Die Zeichenkette, die Du durchsuchst lautet
<img src="http://www.example.org/thumb.php?image\_id=1234" alt="" />
Wie willst Du dort ein "thumb.php5" finden?
4\. Fehler
Nach Deiner ID erwartest Du ein einfaches oder doppeltes Anführungszeichen. In eckigen Klammern befinden sich Alternativen, die Syntax wäre also
['"]
nicht ['|"].
> ist ein Sonderzeichen, das maskiert werden muss, im Kontext hier überflüssig ist.
5\. und 6. Fehler
Nach dem Anführungszeichen erwartest Du nach einem Leer- oder bestimmten Steuerzeichen eine beliebige Zeichenkette, die irgendwann von "/>" gefolgt wird. Du übersiehst, dass solche Suchmuster gierig sind (Fehler 5) und vergisst, dass Du diese Zeichenkette merken musst, um sie wieder einfügen zu können (Fehler 6).
Als grundsätzlichen Fehler könnte man es ansehen, dass Du Suchmuster und Ersatzzeichenkette mit den Referenzen nicht Variablen zuweist sondern alles in eine dadurch sehr unübersichtliche Anweisung quetschst.
Mit diesen meinen Hinweisen müsste es Dir möglich sein, den RegExp zu erstellen.
Freundliche Grüße
Vinzenz
Hallo!
mir hat geholfen und hilft noch immer, dieses wundervolle Tool:
The Regex Coach - interactive regular expressions:
The Regex Coach is a graphical application for Windows and Linux/x86 (also usable on FreeBSD) which can be used to experiment with (Perl-compatible) regular expressions interactively. ...
Gruß,
FF