2009-03-20 7 views
4

Ich versuche, unbenutzte Spannen (d. H. Solche ohne Attribut) aus HTML-Dateien zu entfernen, nachdem ich alle Attribute, die ich nicht wollte, mit anderen regulären Ausdrücken bereinigt habe.Wie kann ich unbenutzte verschachtelte HTML-Span-Tags mit einem Perl-Regex entfernen?

Ich habe ein Problem mit meiner Regex nicht das richtige Paar von Start-und Ende-Tags zu entfernen.

my $a = 'a <span>b <span style="color:red;">c</span> d</span>e'; 
$a =~ s/<span\s*>(.*?)<\/span>/$1/g; 
print "$a\ 

kehrt

a b <span style="color:red;">c d</span>e 

aber ich will es

a b <span style="color:red;">c</span> de 

Hilfe geschätzt zurückzukehren.

+0

Eier, Wurst gebackene Bohnen Schwern

Antwort

11

Versuchen HTML::Parser:

#!/usr/bin/perl 

use strict; 
use warnings; 

use HTML::Parser; 

my @print_span; 
my $p = HTML::Parser->new(
    start_h => [ sub { 
    my ($text, $name, $attr) = @_; 
    if ($name eq 'span') { 
     my $print_tag = %$attr; 
     push @print_span, $print_tag; 
     return if !$print_tag; 
    } 
    print $text; 
    }, 'text,tagname,attr'], 
    end_h => [ sub { 
    my ($text, $name) = @_; 
    if ($name eq 'span') { 
     return if !pop @print_span; 
    } 
    print $text; 
    }, 'text,tagname'], 
    default_h => [ sub { print shift }, 'text'], 
); 
$p->parse_file(\*DATA) or die "Err: $!"; 
$p->eof; 

__END__ 
<html> 
<head> 
<title>This is a title</title> 
</head> 
<body> 
<h1>This is a header</h1> 
a <span>b <span style="color:red;">c</span> d</span>e 
</body> 
</html> 
+0

Vielen Dank, das gibt mir viel zu tun. Ich werde darüber nachdenken müssen, wie Sie das gemacht haben, und ich habe einige zusätzliche Komplikationen zu bewältigen, aber hoffentlich wird das den Trick machen. Das Ziel ist eigentlich, Wort Mist zu bereinigen, der in eine asp.net-Datei mit Masterpages eingefügt wurde. –

6

Verwenden Sie keine regexps für die Verarbeitung (HTML ==) XML. Du weißt nie, welche Eingabe du bekommen wirst. Stellen Sie sich folgendes, gültiges HTML:

a <span>b <span style="color:red;" title="being closed with </span>">c</span> de 

Hätten Sie das gedacht?

Verwenden Sie stattdessen einen XML-Prozessor.

Siehe auch Verwandte Fragen (rechts) für Ihre Frage.

+0

es ist wahr, aber zum Glück habe ich eine bekannte (wenn auch große) Haufen von cruddy html bis zu reinigen, und das ist nicht einer von Die vielen bösen Tricks des Wortes –

+0

wenn es über Wort ist: Hast du dieses gesehen: Säubern von Word's Nasty HTML, http://www.codinghorror.com/blog/archives/000485.html? –

+0

HTML ist nicht gültig, da '<' and '>' in Attributen maskiert werden muss, auch zweiter Bereich ist nicht geschlossen – tig

9

Regex ist nicht stark genug, um HTML (oder XML) zu parsen. Jede Regex, die Sie finden können, wird nicht mit verschiedenen Formulierungen von sogar gültigem HTML übereinstimmen (geschweige denn echte Tag-Suppe).

Dies ist ein Verschachtelungsproblem. Regex kann normalerweise keine Verschachtelung handhaben, aber Perl hat eine nicht-standardmäßige Erweiterung, um Regex-Rekursion zu unterstützen: (? N), wobei n die Gruppennummer ist, in die rekursiv recherchiert werden soll. So etwas wie dies würde beide Spannweiten in Ihrem Beispiel entsprechen:

(<span[^>]*>.*+(?1)?.*+<\/span>) 

perlfaq 6.11 See.

Leider ist dies immer noch nicht genug, weil es sowohl attributierte als auch nicht attributierte < span> Start-Tags zählen kann, so dass das End-Tag </span> eins schließt. Ich kann mir keinen Weg vorstellen, wie das gemacht werden kann, ohne auch die Attribute span start-tags zu vergleichen.

Sie benötigen einen HTML-Parser dafür, und Sie sollten einen trotzdem verwenden, weil Regex für HTML/XML eindeutig die falsche Sache ist.

Verwandte Themen