Texte entre deux balises


23

Je veux récupérer tout ce qui se trouve entre ces deux balises - <tr> </tr>- à partir d'un document html. Maintenant, je n'ai pas d'exigences HTML spécifiques qui justifieraient un analyseur HTML. J'ai simplement besoin de quelque chose qui corresponde <tr>et </tr>obtienne tout entre les deux et il pourrait y avoir plusieurs trs. J'ai essayé awk, qui fonctionne, mais pour une raison quelconque, il finit par me donner des doublons de chaque ligne extraite.

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

Que faire à ce propos?


IIUC votre script awk doit être: '/<tr/{p=1}; p; /<\/tr>/{p=0}'. Publiez un exemple d'entrée et de sortie attendue si cela ne fonctionne pas.
Thor

puisque votre awkfonctionne mais donne des doublons essayez de passer la sortie de votre awk sort -upour les rendre distincts
igiannak

Réponses:


14

Si vous ne voulez que ...de tout, <tr>...</tr>faites:

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

Pour les multilignes:

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

Vérifiez d'abord le HTMLFILE du caractère "|" (pas habituel, mais possible) et s'il existe, changez-en un qui n'existe pas.


1
Cela ne fonctionnera que si les balises de début et de fin sont sur la même ligne.
l0b0

echo "bla<tr>foo</tr>bla<tr>bar</tr>bla" | grep -o '<tr>.*</tr>' | sed 's/\(<tr>\|<\/tr>\)//g'donne fooblabar. Le blane devrait pas être là?
NN

@ l0b0 correct. ira pour un compatible multiligne ...
xx4h

grep -Po '<tr>.*?</tr>'retournerait un résultat par ligne dans le cas de @ NN, mais ce n'est pas portable.
l0b0

Je ne suis pas sûr de ce que vous entendez par `` spécifications '' ou `` style de spécifications '', mais notez que votre navigateur Web utilise un analyseur HTML et qu'un analyseur HTML analysera le HTML, quelle que soit la façon dont il est écrit. Il n'analysera pas les choses qui ne sont pas html, mais votre navigateur ne le fera pas non plus, donc personne ne prendrait la peine d'écrire "html" qu'un analyseur ne peut pas analyser. En d'autres termes: un analyseur décent est certainement votre meilleur pari pour le faire.
goldilocks

11

Vous avez une exigence qui garantit un analyseur HTML: vous devez analyser HTML. Perl HTML :: TreeBuilder , Python BeautifulSoup et d' autres sont faciles à utiliser, plus facile que d' écrire des expressions régulières complexes et fragiles.

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

ou

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

sedet awkne sont pas bien adaptés à cette tâche, vous devriez plutôt utiliser un analyseur html approprié. Par exemple hxselectde w3.org:

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

Je ne sais pas si hxselect est le meilleur choix; Je ne l'ai pas utilisé mais la page de manuel dit qu'il "lit un document XML bien formé", ce que ne sont pas de nombreux documents html. Cela vaut probablement la peine d'essayer. Les bibliothèques d'analyseur html disponibles pour perl, python, et. Al. sera beaucoup mieux, si c'est une option.
goldilocks

2
@goldilocks: Le meilleur choix dépend de la situation. D'après mon expérience, hxselectfait du très bon travail avec des documents html / xml bien formés. En outre, il est plus rapide à utiliser que perl, python et autres. Je pense que hxselectc'est un bon compromis entre sed/ awket les bibliothèques d'analyseurs.
Thor

1
Si ça marche c'est super! J'étais juste en train d'ajouter une mise en garde pour TechJack au cas où cela ne l'aurait pas fait - car j'avais également recommandé d'utiliser une sorte d'analyseur;) Les bibliothèques de programmation sont bien sûr plus gênantes mais devraient traiter tout ce qui est passable à distance en html.
goldilocks

Thor, a l' hxselectair bien, va certainement l'explorer davantage. Merci.
TechJack

@goldilocks: hxnormalizeprend en charge les fichiers html / xml mal formés.
Tokland

5

Si rubyest disponible, vous pouvez effectuer les opérations suivantes

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

fileest votre fichier html d'entrée. La commande exécute un Ruby one-liner. Tout d' abord, il lit toutes les lignes de fileet les joint à une chaîne, readlines.join. Puis, de la chaîne , il sélectionne quoi que ce soit entre (mais non compris) <tr>et <\/tr>qui est un caractère ou plus sans tenir compte de nouvelles lignes, [/(?<=<tr>).+(?=<\/tr>)/m]. Ensuite, il supprime tout <tr>ou </tr>de la chaîne gsub(/<\/?tr>/, "")(cela est nécessaire pour gérer les trbalises imbriquées ). Enfin, elle imprime la chaîne, puts.

Vous avez dit qu'un analyseur HTML n'est pas garanti pour vous, mais qu'il est très facile à utiliser avec Nokogiriruby et rend la commande plus simple.

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

-rnokogiricharge Nokogiri. Nokogiri::HTML(readlines.join)lit toutes les lignes de file. xpath("//tr")sélectionne chaque trélément et map { |e| e.content }sélectionne le contenu de chaque élément, c'est-à-dire ce qui est entre <tr>et </tr>.


1

grep

Pour récupérer le contenu d'une trbalise sur plusieurs lignes, passez-le d' xargsabord, par exemple:

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

Pour renvoyer uniquement du HTML interne, utilisez:

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

Vérifiez la syntaxe des perlremodèles étendus .

Remarque: Pour des performances plus rapides, vous pouvez envisager celui ripgrepqui a une syntaxe similaire.


il s'est imprimé plus agréablement sans les xargs, a été utile pour trouver le javascript en ligne en utilisant egrep -o "<script. *? </script>"
Andrew

0

pup

Exemple utilisant pup(qui utilise des sélecteurs CSS ):

pup -f myfile.html tr

Pour imprimer le texte seulement sans balises, utilisez: pup -f myfile.html tr text{}.

Voici quelques exemples avec curl:

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

xpup

Exemple d'utilisation xpuppour l'analyse HTML / XML (qui prend en charge XPath):

xpup -f myfile.html "//tr"

0

si c'est juste une liste rapide de <tr>s, cela pourrait aider:

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

à votre santé

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.