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?

TechJack
la source
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.

xx4h
la source
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
Gilles 'SO- arrête d'être méchant'
la source
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'
Thor
la source
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>.

NN
la source
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.

kenorb
la source
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"
kenorb
la source
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é

eswues
la source