Je veux récupérer 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 correspond à <tr>
et </tr>
et obtient tout entre les deux et il peut y avoir plusieurs tr
s. 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?
Si vous voulez seulement ...
De tous <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.
Vous avez une exigence qui garantit un analyseur HTML: vous devez analyser HTML. Perl's 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
sed
et awk
ne sont pas bien adaptés à cette tâche, vous devriez plutôt utiliser un analyseur html approprié. Par exemple hxselect
de w3.org:
<htmlfile hxselect -s '\n' -c 'tr'
Si Ruby
est disponible, vous pouvez procéder comme suit
Ruby -e 'puts readlines.join[/(?<=<tr>).+(?=<\/tr>)/m].gsub(/<\/?tr>/, "")' file
où file
est votre fichier html d'entrée. La commande exécute un Ruby one-liner. Premièrement, elle lit toutes les lignes de file
et les joint à une chaîne, readlines.join
. Ensuite, à partir de la chaîne il sélectionne n'importe quoi entre (mais sans inclure) <tr>
et <\/tr>
qui est un caractère ou plus indépendamment des nouvelles lignes, [/(?<=<tr>).+(?=<\/tr>)/m]
. Ensuite, il supprime tout <tr>
ou </tr>
à partir de la chaîne, gsub(/<\/?tr>/, "")
(cela est nécessaire pour gérer les balises tr
imbriquées). Enfin, il 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 Nokogiri avec Ruby
et rend la commande plus simple.
Ruby -rnokogiri -e 'puts Nokogiri::HTML(readlines.join).xpath("//tr").map { |e| e.content }' file
-rnokogiri
Charge 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>
.
grep
Pour récupérer le contenu de la balise tr
sur plusieurs lignes, passez-le d'abord par xargs
, 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 pour perlre
modèles étendus .
Remarque: Pour des performances plus rapides, vous pouvez envisager ripgrep
qui a une syntaxe similaire.
s'il s'agit simplement d'une liste rapide de <tr>
s cela pourrait aider:
Perl -ne 'print if /<tr>/../</tr>/' your.html > TRs.log
à votre santé
pup
Exemple utilisant pup
(qui utilise sélecteurs CSS ):
pup -f myfile.html tr
Pour imprimer uniquement du texte 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 utilisant xpup
pour l'analyse HTML/XML (qui prend en charge XPath):
xpup -f myfile.html "//tr"