Regex seleziona tutto il testo tra i tag


143

Qual è il modo migliore per selezionare tutto il testo tra 2 tag - es: il testo tra tutti i tag "pre" sulla pagina.


2
Il modo migliore è usare un html-parser come "Beautiful Soup" se ti piace il pitone ...
Fredrik Pihl,

1
Il modo migliore è utilizzare il parser XML / HTML.
Daniel O'Hara,

4
In generale, utilizzando le espressioni regolari per analizzare HTML non è una buona idea: stackoverflow.com/questions/1732348/...
murgatroid99

Non analizzare il testo tra i tag con regex perché i tag nidificati in modo arbitrario rendono HTML non regolare. I tag corrispondenti sembrano essere a posto. /<div>.*?<\/div>/.exec("<div><div></div></div>")
jdh8

Risposte:


157

Puoi usare "<pre>(.*?)</pre>"(sostituendo pre con qualunque testo tu voglia) ed estrarre il primo gruppo (per istruzioni più specifiche specificare una lingua) ma questo presuppone l'idea semplicistica che tu abbia HTML molto semplice e valido.

Come hanno suggerito altri commentatori, se stai facendo qualcosa di complesso, usa un parser HTML.


41
Questo non seleziona il testo tra i tag, include i tag.
capikaw,

3
Devi prendere la selezione usando ()
Sahu V Kumar il

2
Per tag a più righe: <html_tag> (. +) ((\ S) + (. +)) + <\ / Html_tag>
Felipe Augusto

Questo ha ancora visibilità quindi: se stai ancora vedendo i <pre>tag dopo aver provato <pre>(.*?)<\/pre>, è perché stai guardando ciò che viene catturato dalla corrispondenza Completa invece del (. *?) Gruppo di acquisizione. Sembra sdolcinato ma penso sempre "parentesi = coppia di ladri" perché a meno che non (sia seguito da un ?come in (?:o (?>, ogni partita avrà due acquisizioni: 1 per la partita completa e 1 per il gruppo di cattura. Ogni set aggiuntivo di parentesi aggiunge un'acquisizione aggiuntiva. Devi solo sapere come recuperare entrambe le acquisizioni in qualsiasi lingua tu stia lavorando.
rbsdca,

137

Il tag può essere completato in un'altra riga. Questo è il motivo \nper cui deve essere aggiunto.

<PRE>(.|\n)*?<\/PRE>

5
Punto importante sull'aggiunta (.|\n)*?quando si tratta di tag HTML su più righe. La risposta selezionata funziona solo se i tag HTML si trovano sulla stessa riga.
Caleuanhopkins,

3
<PRE> (. | \ N | \ r \ n) *? <\ / PRE> per terminazioni di linea di Windows
Segna il

3
Non usare mai (.|\n)*?per abbinare alcun carattere. Utilizzare sempre .con il smodificatore (linea singola). O una [\s\S]*?soluzione alternativa.
Wiktor Stribiżew,

Volevo selezionare i commenti sul codice in notepad ++, quindi usando questa risposta mi è venuto in mente /\*(.|\n)*?\*/che ha fatto il lavoro - grazie
wkille

risposta perfetta grazie mille
Omda

25

Questo è quello che vorrei usare.

(?<=(<pre>))(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|`~]| )+?(?=(</pre>))

Fondamentalmente quello che fa è:

(?<=(<pre>))La selezione deve essere anteposta con <pre>tag

(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|~]| )Questa è solo un'espressione regolare che voglio applicare. In questo caso, seleziona il carattere lettera o cifra o newline o alcuni caratteri speciali elencati nell'esempio tra parentesi quadre. Il carattere pipe |significa semplicemente " OR ".

+?Inoltre, il personaggio afferma di selezionare uno o più dei precedenti: l'ordine non ha importanza. Il punto interrogativo cambia il comportamento predefinito da "goloso" a "non gradevole".

(?=(</pre>))La selezione deve essere aggiunta dal </pre>tag

inserisci qui la descrizione dell'immagine

A seconda del tuo caso d'uso potresti dover aggiungere alcuni modificatori come ( i o m )

  • i - senza distinzione tra maiuscole e minuscole
  • m - ricerca su più righe

Qui ho eseguito questa ricerca in Sublime Text, quindi non ho dovuto usare modificatori nel mio regex.

Javascript non supporta lookbehind

L'esempio sopra dovrebbe funzionare bene con linguaggi come PHP, Perl, Java ... Javascript, tuttavia, non supporta lookbehind, quindi dobbiamo dimenticare di usare (?<=(<pre>))e cercare qualche tipo di soluzione alternativa. Forse è sufficiente rimuovere i primi quattro caratteri dal nostro risultato per ogni selezione come qui Regex abbina il testo tra i tag

Guarda anche la DOCUMENTAZIONE DEL REGICE JAVASCRIPT per le parentesi non catturanti


Nota che devi mettere i caratteri di virgoletta singola / doppia con `per mettere il regexp in una stringa.
David Zwart,

18

utilizzare il modello seguente per ottenere il contenuto tra gli elementi. Sostituisci [tag]con l'elemento reale da cui desideri estrarre il contenuto.

<[tag]>(.+?)</[tag]>

A volte i tag avranno attributi, come i anchortag che hanno href, quindi usano il modello seguente.

 <[tag][^>]*>(.+?)</[tag]>

Prova il primo esempio come "<head> (. +?) </head>" e funziona come previsto. Ma non ho risultati con il secondo.
Alex Byrth,

1
questo non funziona. <[tag]>abbinerà <t>, <a>e<g>
Martin Schneider

2
@ MA-Maddin - Penso che ti sia persa la Replace [tag] with the actual element you wish to extract the content fromparte.
LWC,

2
Oh bene, si. Questi []avrebbero dovuto essere omessi del tutto. Ciò sarebbe più chiaro, a causa del loro significato in RegEx e del fatto, che le persone scansionano prima il codice e leggono il testo dopo;)
Martin Schneider,

15

Per escludere i tag di delimitazione:

(?<=<pre>)(.*?)(?=</pre>)

(?<=<pre>) cerca il testo dopo <pre>

(?=</pre>) cerca prima il testo </pre>

I risultati verranno scritti all'interno del pretag


Le persone che usano questo sguardo alla risposta di @krishna thakor che può anche considerare se il contenuto ha una nuova linea tra i tag
KingKongCoder

Ciò ha aiutato nel mio caso (non è necessario considerare le nuove linee). Grazie.
Pking

6

Non dovresti provare ad analizzare HTML con regex per vedere questa domanda e come si è rivelata.

In parole povere, html non è un linguaggio normale, quindi non è possibile analizzarlo completamente con espressioni regolari.

Detto questo, puoi analizzare sottoinsiemi di html quando non ci sono tag simili nidificati. Quindi, fintanto che qualcosa tra e non è quel tag stesso, questo funzionerà:

preg_match("/<([\w]+)[^>]*>(.*?)<\/\1>/", $subject, $matches);
$matches = array ( [0] => full matched string [1] => tag name [2] => tag content )

Un'idea migliore è quella di utilizzare un parser, come il DOMDocument nativo, per caricare l'html, quindi selezionare il tag e ottenere l'html interno che potrebbe assomigliare a questo:

$obj = new DOMDocument();
$obj -> load($html);
$obj -> getElementByTagName('el');
$value = $obj -> nodeValue();

E poiché si tratta di un parser corretto, sarà in grado di gestire tag di nidificazione ecc.


2
Voglio solo dire che sono un po 'disturbato dal fatto che questo stia ancora raccogliendo downvotes mentre è l'unica risposta che fornisce una soluzione adeguata accanto a quella regex e ho anche aggiunto un ampio avvertimento che probabilmente non è il modo giusto ... Almeno commenta cosa c'è di così sbagliato nella mia risposta, per favore.
sg3s

1
La domanda non è stata taggata con php. Non sono sicuro di come PHP sia entrato in scena ...
trincot

@trincot Questo è successo più di 7 anni fa, quindi non ricordo. In ogni caso è un esempio di risoluzione del problema con una regex e con un parser. Il regex è buono e php è proprio quello che sapevo bene al momento.
sg3s

Capisco, ho visto il tuo primo commento e ho pensato che questo potesse spiegare alcuni dei voti negativi.
trincot


4

Questa sembra essere la più semplice espressione regolare di tutto ciò che ho trovato

(?:<TAG>)([\s\S]*)(?:<\/TAG>)
  1. Escludere il tag di apertura (?:<TAG>)dalle partite
  2. Includi qualsiasi spazio bianco o non spazio bianco ([\s\S]*)nelle partite
  3. Escludere il tag di chiusura (?:<\/TAG>)dalle partite

3

Questa risposta suppone il supporto per guardarsi intorno! Ciò mi ha permesso di identificare tutto il testo tra coppie di tag di apertura e chiusura. Questo è tutto il testo tra '>' e '<'. Funziona perché guardarsi intorno non consuma i personaggi che corrisponde.

(? <=>) ([\ W \ s] +) (? = </)

L'ho provato in https://regex101.com/ usando questo frammento HTML.

<table>
<tr><td>Cell 1</td><td>Cell 2</td><td>Cell 3</td></tr>
<tr><td>Cell 4</td><td>Cell 5</td><td>Cell 6</td></tr>
</table>

È un gioco di tre parti: lo sguardo dietro, il contenuto e lo sguardo davanti.

(?<=>)    # look behind (but don't consume/capture) for a '>'
([\w\s]+) # capture/consume any combination of alpha/numeric/whitespace
(?=<\/)   # look ahead  (but don't consume/capture) for a '</'

cattura dello schermo da regex101.com

Spero che serva da inizio per 10. Fortuna.


Grazie. Non solo questa è una risposta migliore, ma anche un ottimo collegamento al sito regex101. Upvoted! 🙂
Sean Feldman,

2

var str = "Lorem ipsum <pre>text 1</pre> Lorem ipsum <pre>text 2</pre>";
    str.replace(/<pre>(.*?)<\/pre>/g, function(match, g1) { console.log(g1); });

Poiché la risposta accettata è senza codice javascript, quindi aggiungendo che:


1

preg_match_all(/<pre>([^>]*?)<\/pre>/,$content,$matches)questa regex selezionerà tutto tra i tag. non importa se è in una nuova linea (lavora con multilinea.


1

In Python, l'impostazione della DOTALLbandiera catturerà tutto, comprese le nuove linee.

Se è stato specificato il flag DOTALL, questo corrisponde a qualsiasi carattere inclusa una nuova riga. docs.python.org

#example.py using Python 3.7.4  
import re

str="""Everything is awesome! <pre>Hello,
World!
    </pre>
"""

# Normally (.*) will not capture newlines, but here re.DOTATLL is set 
pattern = re.compile(r"<pre>(.*)</pre>",re.DOTALL)
matches = pattern.search(str)

print(matches.group(1))

python example.py

Hello,
World!

Catturare il testo tra tutti i tag di apertura e chiusura in un documento

È utile acquisire il testo tra tutti i tag di apertura e chiusura in un documento finditer. Nell'esempio seguente, <pre>nella stringa sono presenti tre tag di apertura e chiusura .

#example2.py using Python 3.7.4
import re

# str contains three <pre>...</pre> tags
str = """In two different ex-
periments, the authors had subjects chat and solve the <pre>Desert Survival Problem</pre> with a
humorous or non-humorous computer. In both experiments the computer made pre-
programmed comments, but in study 1 subjects were led to believe they were interact-
ing with another person. In the <pre>humor conditions</pre> subjects received a number of funny
comments, for instance: “The mirror is probably too small to be used as a signaling
device to alert rescue teams to your location. Rank it lower. (On the other hand, it
offers <pre>endless opportunity for self-reflection</pre>)”."""

# Normally (.*) will not capture newlines, but here re.DOTATLL is set
# The question mark in (.*?) indicates non greedy matching.
pattern = re.compile(r"<pre>(.*?)</pre>",re.DOTALL)

matches = pattern.finditer(str)


for i,match in enumerate(matches):
    print(f"tag {i}: ",match.group(1))

python example2.py

tag 0:  Desert Survival Problem
tag 1:  humor conditions
tag 2:  endless opportunity for self-reflection

0

Per più righe:

<htmltag>(.+)((\s)+(.+))+</htmltag>


0

Io uso questa soluzione:

preg_match_all( '/<((?!<)(.|\n))*?\>/si',  $content, $new);
var_dump($new);

-1

In Javascript (tra gli altri), questo è semplice. Copre gli attributi e più righe:

/<pre[^>]*>([\s\S]*?)<\/pre>/

-4
<pre>([\r\n\s]*(?!<\w+.*[\/]*>).*[\r\n\s]*|\s*[\r\n\s]*)<code\s+(?:class="(\w+|\w+\s*.+)")>(((?!<\/code>)[\s\S])*)<\/code>[\r\n\s]*((?!<\w+.*[\/]*>).*|\s*)[\r\n\s]*<\/pre>

6
Si prega di introdurre / spiegare la risposta usando le parole.
Andrew Regan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.