Come posso rimuovere un intero tag HTML (e il suo contenuto) dalla sua classe utilizzando una regex?
Domanda
Non sono molto bravo con Regex ma sto imparando.
Vorrei rimuovere alcuni tag html dal nome della classe.Questo è quello che ho finora:
<div class="footer".*?>(.*?)</div>
Il primo .*?è perché potrebbe contenere altri attributi e il secondo è che potrebbe contenere altro materiale HTML.
Che cosa sto facendo di sbagliato?Ho provato molti set senza successo.
Aggiornamento
All'interno del DIV può contenere più righe e sto giocando con Perl regex.
Soluzione
Dovrai anche consentire altre cose prima della lezione nel tag div
<div[^>]*class="footer"[^>]*>(.*?)</div>
Inoltre, fai distinzione tra maiuscole e minuscole. Potrebbe essere necessario sfuggire a cose come le virgolette o la barra nel tag di chiusura. In quale contesto lo stai facendo?
Si noti inoltre che l'analisi HTML con espressioni regolari può essere molto sgradevole, a seconda dell'input. Un buon punto è riportato in una risposta di seguito - supponi di avere una struttura come:
<div>
<div class="footer">
<div>Hi!</div>
</div>
</div>
Cercare di creare una regex per questo è una ricetta per il disastro. La soluzione migliore è caricare il documento in un DOM ed eseguire manipolazioni su di esso.
Pseudocodice che dovrebbe essere strettamente associato a XML :: DOM:
document = //load document
divs = document.getElementsByTagName("div");
for(div in divs) {
if(div.getAttributes["class"] == "footer") {
parent = div.getParent();
for(child in div.getChildren()) {
// filter attribute types?
parent.insertBefore(div, child);
}
parent.removeChild(div);
}
}
Ecco una libreria perl, HTML :: DOM , e un'altra, XML :: DOM
.NET ha librerie integrate per gestire l'analisi dom.
Altri suggerimenti
Come hanno detto altre persone, l'HTML è notoriamente complicato da gestire con l'utilizzo delle regex e un approccio DOM potrebbe essere migliore. Per esempio:.
use HTML::TreeBuilder::XPath;
my $tree = HTML::TreeBuilder::XPath->new;
$tree->parse_file( 'yourdocument.html' );
for my $node ( $tree->findnodes( '//*[@class="footer"]' ) ) {
$node->replace_with_content; # delete element, but not the children
}
print $tree->as_HTML;
In Perl hai bisogno di /s
modificatore, altrimenti il punto non corrisponderà a una nuova riga.
Detto questo, utilizzare un parser HTML o XML adeguato per rimuovere parti indesiderate di un file HTML è molto più appropriato.
<div[^>]*class="footer"[^>]*>(.*?)</div>
Ha funzionato per me, ma era necessario utilizzare barre rovesciate prima dei caratteri speciali
<div[^>]*class=\"footer\"[^>]*>(.*?)<\/div>
Dipende in parte dall'esatto motore regex che stai usando - quale lingua ecc. Ma una possibilità è che devi evitare le virgolette e / o la barra. Potresti anche renderlo insensibile alle maiuscole.
<div class=\"footer\".*?>(.*?)<\/div>
Altrimenti, specifica la lingua / la piattaforma che stai utilizzando: .NET, java, perl ...
Prova questo:
<([^\s]+).*?class="footer".*?>([.\n]*?)</([^\s]+)>
Il tuo problema più grande saranno i tag nidificati. Ad esempio:
<div class="footer"><b></b></div>
La regexp fornita corrisponderebbe a tutto attraverso </b>
, lasciando </div>
alla fine. Dovrai supporre che il tag che stai cercando non abbia elementi nidificati, oppure dovrai usare una sorta di parser da HTML a DOM e una query XPath per rimuovere un intero sotto-albero.
Questo sarà complicato a causa dell'avidità delle espressioni regolari, (Nota che i miei esempi possono sono specifici del perl, ma so che l'avidità è un problema generale con le RE.) Il secondo < / div >
, quindi se disponi di quanto segue:
< div class = " SomethingElse " > < div class = " footer " > cose < / div > < / div >
L'espressione corrisponderà:
< div class = " footer " > cose < / div > < / div >
che non è probabilmente quello che vuoi.
perché non < div class = " footer ". *? < / div >
Non sono neanche un guru regex, ma non penso che tu debba specificare l'ultimo parentesi per il tag div aperto