Testo tra due tag


23

Voglio recuperare qualsiasi cosa si trovi tra questi due tag - <tr> </tr>- da un documento HTML. Ora non ho requisiti html specifici che sarebbero giustificati per un parser html. Ho semplicemente bisogno di qualcosa che corrisponda <tr>e </tr>che ottenga tutto nel mezzo e potrebbero esserci più trs. Ho provato awk, che funziona, ma per qualche motivo finisce per darmi duplicati di ogni riga estratta.

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

Come procedere?


IIUC lo script awk dovrebbe essere: '/<tr/{p=1}; p; /<\/tr>/{p=0}'. Pubblica alcuni esempi di input e output previsti se non funzionano.
Thor,

dato che awksort -u
stai

Risposte:


14

Se vuoi solo fare ...tutto <tr>...</tr>:

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

Per multiline fare:

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

Controlla il HTMLFILE prima del carattere "|" (non al solito, ma possibile) e se esiste, cambia in uno che non esiste.


1
Funzionerà solo se i tag di inizio e fine si trovano sulla stessa riga.
10

echo "bla<tr>foo</tr>bla<tr>bar</tr>bla" | grep -o '<tr>.*</tr>' | sed 's/\(<tr>\|<\/tr>\)//g'fooblabar. Non bladovrebbe essere lì?
NN,

@ l0b0 corretto. andrà per uno compatibile multilinea ...
xx4h

grep -Po '<tr>.*?</tr>'restituirebbe un risultato per riga nel caso di @NN, ma non è portatile.
10

Non sono sicuro di cosa intendi per "specifiche" o "stile delle specifiche", ma nota che il tuo browser web utilizza un parser html e un parser html analizzerà html indipendentemente da come è scritto. Non analizzerà cose che non sono html, ma poi, nemmeno il tuo browser, quindi nessuno si preoccuperebbe di scrivere "html" che un parser non può analizzare. In altre parole: un parser decente è sicuramente la soluzione migliore per farlo.
Riccioli d'oro,

11

Hai un requisito che richiede un parser HTML: devi analizzare HTML. HTML di Perl :: TreeBuilder , BeautifulSoup di Python e altri sono facili da usare, più facili che scrivere espressioni regolari complesse e fragili.

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

sede awknon sono adatti per questa attività, è preferibile utilizzare un parser html appropriato. Ad esempio hxselectda w3.org:

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

Non so se hxselect sia la scelta migliore; Non l'ho usato ma la pagina man dice che "legge un documento XML ben formato" che molti documenti HTML non lo sono. Probabilmente vale la pena provare. Le librerie html parser disponibili per perl, python, et. al. sarà molto meglio, se questa è un'opzione.
Riccioli d'oro,

2
@goldilocks: la scelta migliore dipende dalla situazione. Nella mia esperienza hxselectfa un buon lavoro con documenti html / xml ben formati. Inoltre, è più veloce da usare di perl, python e altri. Penso che hxselectsia una buona via di mezzo tra sed/ awke librerie parser.
Thor,

1
Se funziona è fantastico! Stavo solo aggiungendo un avvertimento per TechJack nel caso in cui non lo fosse - dal momento che avevo anche raccomandato di utilizzare un qualche tipo di parser;) I programmi di programmazione lib sono ovviamente più imbarazzanti, ma dovrebbero trattare qualsiasi cosa passabile da remoto come HTML.
Riccioli d'oro,

Thor, hxselectsembra buono, lo esplorerà sicuramente di più. Grazie.
TechJack,

@goldilocks: hxnormalizesi occupa dei file html / xml non ben formati.
tokland,

5

Se rubyè disponibile è possibile effettuare le seguenti operazioni

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

dov'è il filetuo file html di input. Il comando esegue un Ruby one-liner. Innanzitutto, legge tutte le righe filee le unisce a una stringa readlines.join. Poi, dalla stringa seleziona nulla tra (esclusi) <tr>e <\/tr>che è un carattere o più indipendentemente newlines, [/(?<=<tr>).+(?=<\/tr>)/m]. Quindi, rimuove qualsiasi <tr>o </tr>dalla stringa gsub(/<\/?tr>/, "")(questo è necessario per gestire i trtag nidificati ). Infine, si stampa la stringa, puts.

Hai detto che un parser html non è garantito per te, ma è molto facile usare Nokogiri con rubye semplifica il comando.

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

-rnokogiricarica Nokogiri. Nokogiri::HTML(readlines.join)legge tutte le righe di file. xpath("//tr")seleziona ogni trelemento e map { |e| e.content }seleziona il contenuto di ciascun elemento, ovvero cosa c'è tra <tr>e </tr>.


1

grep

Per recuperare il contenuto all'interno del trtag su più righe, passalo xargsprima, ad esempio:

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

Per restituire solo HTML interno, utilizzare:

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

Controllare la sintassi per perlremotivi estesi .

Nota: per prestazioni più rapide, è possibile prendere in considerazione la ripgrepsintassi simile.


è risultato più bello senza gli xargs, è stato utile trovare javascript inline usando egrep -o "<script. *? </script>"
Andrew

0

pup

Esempio di utilizzo pup(che utilizza selettori CSS ):

pup -f myfile.html tr

Per stampare solo il testo senza modifiche, uso: pup -f myfile.html tr text{}.

Ecco alcuni esempi con curl:

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

xpup

Esempio di utilizzo xpupper l'analisi HTML / XML (che supporta XPath):

xpup -f myfile.html "//tr"

0

se è solo un breve elenco di <tr>s questo potrebbe aiutare:

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

Saluti

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.