Texto entre duas tags

22

Eu quero recuperar o que há entre essas duas tags - <tr> </tr> - de um documento html. Agora eu não tenho nenhum requisito html específico que justifique para um analisador html. Eu simplesmente preciso de algo que corresponda a <tr> e </tr> e obtenha tudo no meio e que possa haver vários tr s. Eu tentei o awk, que funciona, mas por algum motivo ele acaba me dando duplicatas de cada linha extraída.

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

Como fazer isso?

    
por TechJack 13.02.2013 / 12:43

6 respostas

12

Se você quiser apenas ... de todo <tr>...</tr> do:

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

Para multilinha:

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

Verifique o HTMLFILE primeiro do caractere "|" (não é usual, mas possível) e se existir, mude para um que não existe.

    
por 13.02.2013 / 12:53
11

Você tem um requisito que garante um analisador de HTML: você precisa analisar HTML. HTML :: TreeBuilder do Perl, o Python BeautifulSoup e outros são fáceis de usar, mais fáceis do que escrever expressões regulares complexas e frágeis.

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
    
por 14.02.2013 / 02:13
9

sed e awk não são adequados para esta tarefa, você deve usar um analisador html adequado. Por exemplo, hxselect de w3.org:

<htmlfile hxselect -s '\n' -c 'tr'
    
por 13.02.2013 / 13:25
5

Se ruby estiver disponível, você pode fazer o seguinte

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

onde file é seu arquivo html de entrada. O comando executa um one-liner Ruby. Primeiro, ele lê todas as linhas de file e as associa a uma string, readlines.join . Então, a partir da string, ele seleciona qualquer coisa entre (mas não incluindo) <tr> e <\/tr> que é um caractere ou mais, independentemente de novas linhas, [/(?<=<tr>).+(?=<\/tr>)/m] . Em seguida, remove qualquer <tr> ou </tr> da sequência, gsub(/<\/?tr>/, "") (isso é necessário para manipular tags tr aninhadas). Finalmente, imprime a string, puts .

Você disse que um analisador html não é garantido para você, mas é muito fácil de usar Nokogiri com ruby e torna o comando mais simples .

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

-rnokogiri carrega o Nokogiri. Nokogiri::HTML(readlines.join) lê todas as linhas de file . xpath("//tr") seleciona cada elemento tr e map { |e| e.content } seleciona o conteúdo de cada elemento, ou seja, o que está entre <tr> e </tr> .

    
por 13.02.2013 / 20:01
0

pup

Exemplo usando pup (que usa Seletores CSS ):

pup -f myfile.html tr

Para imprimir apenas texto sem tags, use: pup -f myfile.html tr text{} .

Aqui estão alguns exemplos com curl :

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

xpup

Exemplo usando xpup para análise HTML / XML (que suporta XPath):

xpup -f myfile.html "//tr"
    
por 12.04.2018 / 18:06
0

grep

Para recuperar o conteúdo na tag tr em várias linhas, passe-o pelo xargs primeiro, por exemplo:

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

Para retornar somente HTML interno, use:

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

Verifique a sintaxe dos perlre padrões estendidos .

Observação: para obter um desempenho mais rápido, você pode considerar ripgrep que tem uma sintaxe semelhante.

    
por 12.04.2018 / 17:50