Texto entre dos etiquetas


23

Quiero recuperar lo que sea que esté entre estas dos etiquetas <tr> </tr>- de un documento html. Ahora no tengo ningún requisito html específico que garantice un analizador html. Simplemente necesito algo que coincida <tr>y </tr>consiga todo en el medio y podría haber múltiples correos trelectrónicos. Intenté awk, que funciona, pero por alguna razón termina dándome duplicados de cada fila extraída.

awk '
/<TR/{p=1; s=$0}
p && /<\/TR>/{print $0 FS s; s=""; p=0}
p' htmlfile> newfile

¿Como va esto?


IIUC su script awk debe ser: '/<tr/{p=1}; p; /<\/tr>/{p=0}'. Publique alguna entrada de ejemplo y salida esperada si no funciona.
Thor

Debido a que su awkestá trabajando, pero dando duplicados tratar de pasar la salida de su awk de sort -uconseguirlos distinta
igiannak

Respuestas:


14

Si solo quieres ...de todo <tr>...</tr>haz:

grep -o '<tr>.*</tr>' HTMLFILE | sed 's/\(<tr>\|<\/tr>\)//g' > NEWFILE

Para multilínea hacer:

tr "\n" "|" < HTMLFILE | grep -o '<tr>.*</tr>' | sed 's/\(<tr>\|<\/tr>\)//g;s/|/\n/g' > NEWFILE

Verifique el ARCHIVO HTML primero del carácter "|" (no habitual, pero posible) y si existe, cambie a uno que no existe.


1
Eso solo funcionará si las etiquetas de inicio y fin están en la misma línea.
l0b0

echo "bla<tr>foo</tr>bla<tr>bar</tr>bla" | grep -o '<tr>.*</tr>' | sed 's/\(<tr>\|<\/tr>\)//g'da fooblabar. El blano debería estar allí?
NN

@ l0b0 correcto. irá por uno compatible con
varias líneas

grep -Po '<tr>.*?</tr>'devolvería un resultado por línea en el caso de @ NN, pero no es portátil.
l0b0

No estoy seguro de lo que quiere decir con 'especificaciones' o 'estilo de especificaciones', pero tenga en cuenta que su navegador web utiliza un analizador html y un analizador html analizará html independientemente de cómo esté escrito. No analizará cosas que no son html, pero tampoco lo hará su navegador, por lo que nadie se molestaría en escribir "html" que un analizador no pueda analizar. En otras palabras: un analizador decente es sin duda su mejor apuesta para hacer esto.
Ricitos de oro

11

Tiene un requisito que garantiza un analizador HTML: necesita analizar HTML. El HTML :: TreeBuilder de Perl , BeautifulSoup de Python y otros son fáciles de usar, más fáciles que escribir expresiones regulares frágiles y complejas.

perl -MHTML::TreeBuilder -le '
    $html = HTML::TreeBuilder->new_from_file($ARGV[0]) or die $!;
    foreach ($html->look_down(_tag => "tr")) {
        print map {$_->as_HTML()} $_->content_list();
    }
' input.html

o

python -c 'if True:
    import sys, BeautifulSoup
    html = BeautifulSoup.BeautifulSoup(open(sys.argv[1]).read())
    for tr in html.findAll("tr"):
        print "".join(tr.contents)
' input.html

9

sedy awkno son adecuados para esta tarea, debería usar un analizador html adecuado. Por ejemplo hxselectde w3.org:

<htmlfile hxselect -s '\n' -c 'tr'

No sé si hxselect es la mejor opción; No lo he usado, pero la página del manual dice que "lee un documento XML bien formado" que muchos documentos html no son. Probablemente vale la pena intentarlo. Las bibliotecas de analizador html disponibles para perl, python, et. Alabama. será mucho mejor, si esa es una opción.
Ricitos de oro

2
@goldilocks: la mejor opción depende de la situación. En mi experiencia hxselecthace un trabajo bastante bueno con documentos html / xml bien formados. Además, es más rápido de usar que perl, python y otros. Creo que hxselectes un buen término medio entre sed/ awky las librerías de analizador.
Thor

1
Si funciona, ¡genial! Solo estaba agregando una advertencia para TechJack en caso de que no lo hiciera, ya que también recomendé usar algún tipo de analizador;) Las de lib de programación son, por supuesto, más incómodas, pero deberían tratar cualquier cosa remotamente aceptable como html.
Ricitos de oro

Thor, se hxselectve bien, definitivamente lo explorará más. Gracias.
TechJack

@goldilocks: hxnormalizese encarga de archivos html / xml mal formados.
tokland

5

Si rubyestá disponible, puede hacer lo siguiente

ruby -e 'puts readlines.join[/(?<=<tr>).+(?=<\/tr>)/m].gsub(/<\/?tr>/, "")' file

¿Dónde fileestá su archivo html de entrada? El comando ejecuta un Ruby one-liner. En primer lugar, se lee todas las líneas de filey se une a ellos en una cadena, readlines.join. Luego, a partir de la cadena se selecciona entre nada (pero sin incluir) <tr>y <\/tr>que es uno de los personajes o más, independientemente de los saltos de línea, [/(?<=<tr>).+(?=<\/tr>)/m]. Luego, elimina cualquiera <tr>o </tr>de la cadena gsub(/<\/?tr>/, "")(esto es necesario para manejar tretiquetas anidadas ). Por último, se imprime la cadena, puts.

Dijiste que un analizador html no está garantizado para ti, pero es muy fácil de usar con Nokogiriruby y hace que el comando sea más simple.

ruby -rnokogiri -e 'puts Nokogiri::HTML(readlines.join).xpath("//tr").map { |e| e.content }' file

-rnokogiricarga Nokogiri. Nokogiri::HTML(readlines.join)lee todas las líneas de file. xpath("//tr")selecciona cada trelemento y map { |e| e.content }selecciona el contenido de cada elemento, es decir, lo que está entre <tr>y </tr>.


1

grep

Para recuperar contenido dentro de la tretiqueta en varias líneas, páselo xargsprimero, por ejemplo:

curl -sL https://www.iana.org/ | xargs | egrep -o "<tr>.*?</tr>"

Para devolver solo HTML interno, use:

curl -sL https://www.iana.org/ | xargs | grep -Po "<tr>\K(.*?)</tr>" | sed "s/..tr.//g"

Verifique la sintaxis para perlrepatrones extendidos .

Nota: Para un rendimiento más rápido, puede considerar ripgrepcuál tiene una sintaxis similar.


se imprimió mejor sin los xargs, fue útil para encontrar JavaScript en línea usando egrep -o "<script. *? </script>"
Andrew

0

pup

Ejemplo usando pup(que usa selectores CSS ):

pup -f myfile.html tr

Para imprimir sólo texto sin etiquetas, utilice: pup -f myfile.html tr text{}.

Aquí hay algunos ejemplos con curl:

curl -sL https://www.iana.org/ | pup tr text{}
pup -f <(curl -sL https://www.iana.org/) tr text{}

xpup

Ejemplo de uso xpuppara el análisis HTML / XML (que admite XPath):

xpup -f myfile.html "//tr"

0

si es solo una lista rápida de <tr>s, esto podría ayudar:

perl -ne 'print if /<tr>/../</tr>/' your.html > TRs.log

aclamaciones

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.