Thread Suche und Ersetzen von <?php und <!--
(15 answers)
Opened by newperler at 2011-04-26 19:20 2011-04-28T06:39:20 newperler In >99% der Fälle kannst Du mit relativ einfachen Regex Deine Aufgabe erledigen, weil zwischen dem Start von <?php und dem abschließenden ?> nichts kommt, was Deine Regex aus dem Tritt bringen würde. Wenn Du Kontrolle über die Files hast, die Du einliest (oder zumindest die Skripte/Programme die sie erzeugen) kannst Du die Quote wahrscheinlich sogar auf >99.99% hochtreiben. Aber mit einfachen Regex wirst Du nie alle Ausnahmefälle abdecken können. Irgendwann kracht es dann, weil Dein Skript nicht mit gültigem HTML zurechtkommt. Für die HTML-Kommentare gilt im Prinzip das gleiche, wobei hier das Fehlerpotenzial tendenziell höher ist, weil Kommentare eben nicht durch <!-- am Anfang und --> am Ende definiert sind sondern innerhalb eines <! ... >[c] durch [c]-- ein- und wieder ausgeschaltet werden. Wenn Du auf der sicheren Seite sein willst, verwende HTML::Parser. Der kommt mit den Sonderfällen zurecht. Mit HTML::TreeBuider ist das sehr einfach (ungetestetes Code-Fragment): Code (perl): (dl
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 use HTML::TreeBuilder; # TreeBulder-Objekt anlegen my $tree = HTML::TreeBuilder-new(); # HTML-File einlesen $tree->parse_file($filename); # HTML aus String einlesen $tree->parse($htmlinput); # weitere Zeilen: $tree->parse($htmlinput2); $tree->eof(); # eingabe beendet # Ausgabe my $output = $tree->as_HTML(); Je nachdem, ob Du das HTML direkt aus dem File oder aus einem String einlesen willst, musst Du Zeile 7 bzw. 10-12 auskommentieren. Und das Beste für Dich: die php-Tags und HTML-Kommentare entfernt HTML::TreeBuilder schon in der Defaulteinstellung. (Und kleinere Probleme in der HTML-Syntax werden ebenfalls gefixt.) Falls Du kein komplettes HTML-Dokument einliest, sondern nur Ausschnitte (und auch nur diese Ausschnitte zurückhaben willst), wird die Ausgabe etwas komplizierter (ebenfalls ungetestet): Code (perl): (dl
)
my @htmlparts = map {$_->as_HTML()} $tree->guts(); Zur Erklärung: $tree-guts() liefert eine Liste mit allen Teilen des HTML-Trees, die du via parse eingegeben hast. Umgebende <html> Tags, die der TreeBuilder selbst hinzufügt, um einen gültigen HTML-Tree zu bekommen, werden dabei weggelassen. map {$_->as_HTML()} verwandelt die Teilbäume dann wieder in HTML. ACHTUNG: Ich habe gerade einen kurzen Blick in das Skript geworfen und dabei noch einige sehr unsichere Regex gefunden. So wird z.B. nach <meta name="description" content="..."> gesucht. Das funktioniert auch (solange die Quotes um description balanced sind und in content kein unescaped " oder ' steht). Aber wenn stattdessen im HTML <meta content="..." name="description"> steht - was von der Bedeutung völlig equivalent ist - wird es nicht mehr gefunden. Wenn Du Dein HTML durch den TreeBuilder jagst, ist nicht mehr garantiert, dass die Reihenfolge der Attribute in der Ausgabe unverändert ist. Die obige Regex würde nur noch mit einer 50%-Chance zuschlagen. (Das gleiche Problem tritt auf, wenn die Reihenfolge in der Source getauscht wird.) Saubere Programmierung wäre, dass HTML-Dokument in den HTML::TreeBuilder zuladen, dann den Tree nach einem Element tag='meta' mit dem Attribute name=description zu durchsuchen und in in diesem Element das Attribut 'content' auszuwerten. Das geht recht einfach und ist sehr robust, weil Du Dich um Quotes, die Reihenfolge der Attribute u.ä. nicht kümmern musst - das machen Parser/TreeBuilder für Dich und HTML::TreeBuilder hat sehr leistungsfähige und komfortable Methoden zum Durchsuchen des HTML-Trees. Allerdings ist es natürlich trotzdem Arbeit das ganze Skript umzustellen. |