Текст между двумя тегами


23

Я хочу получить то, что находится между этими двумя тегами <tr> </tr>- из HTML-документа. Теперь у меня нет особых требований к html, которые гарантировали бы наличие html-парсера. Мне просто нужно что-то, что соответствует <tr>и </tr>получает все промежуточное, и может быть несколько trs. Я попробовал awk, который работает, но по какой-то причине он дает мне дубликаты каждой извлеченной строки.

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

Как это сделать?


IIUC ваш AWK сценарий должен быть: '/<tr/{p=1}; p; /<\/tr>/{p=0}'. Опубликуйте пример ввода и ожидаемый вывод, если он не работает.
Тор

так как ваш awkработает, но выдает дубликаты, попробуйте передать выходные данные вашего awk, sort -uчтобы они отличались
друг

Ответы:


14

Если вы только хотите ...всего, <tr>...</tr>сделайте:

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

Для многострочного:

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

Проверьте HTMLFILE первым из символа "|" (не обычно, но возможно), и если он существует, измените на тот, который не существует.


1
Это будет работать только в том случае, если начальный и конечный теги находятся на одной строке.
10

echo "bla<tr>foo</tr>bla<tr>bar</tr>bla" | grep -o '<tr>.*</tr>' | sed 's/\(<tr>\|<\/tr>\)//g'дает fooblabar. Там blaне должно быть?
NN

@ l0b0 правильно. пойдет на мультилинейно-совместимый ...
xx4h

grep -Po '<tr>.*?</tr>'вернул бы один результат на строку в случае @ NN, но он не переносим.
10

Я не уверен, что вы подразумеваете под «specs» или «spec-style», но учтите, что ваш веб-браузер использует html-анализатор, и html-анализатор будет анализировать html независимо от того, как он написан. Он не будет анализировать вещи, которые не являются HTML, но и ваш браузер не будет, поэтому никто не потрудится написать «HTML», который анализатор не сможет проанализировать. Другими словами: достойный синтаксический анализатор, безусловно, ваш лучший выбор для этого.
Златовласка

11

У вас есть требование, которое гарантирует анализатор HTML: вам нужно проанализировать HTML. HTML :: TreeBuilder , Python's BeautifulSoup и другие в Perl просты в использовании, проще, чем написание сложных и хрупких регулярных выражений.

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

или

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

sedи awkне очень хорошо подходят для этой задачи, вы должны использовать правильный анализатор HTML. Например hxselectиз w3.org:

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

Я не знаю, является ли hxselect лучшим выбором; Я не использовал его, но на справочной странице написано, что он «читает правильно сформированный XML-документ», чего нет во многих HTML-документах. Вероятно, стоит попробовать. Доступны библиотеки синтаксического анализа html для perl, python, et. и др. будет намного лучше, если это вариант.
Златовласка

2
@goldilocks: Лучший выбор зависит от ситуации. По моему опыту hxselectхорошо справляется с хорошо сформированными документами html / xml. Кроме того, он быстрее в использовании, чем Perl, Python и другие. Я думаю, что hxselectэто хорошая середина между sed/ awkи парсерами.
Thor

1
Если это работает, это здорово! Я просто добавил предостережение для TechJack на случай, если этого не произойдет - поскольку я также рекомендовал использовать какой-то синтаксический анализатор;) Программы для lib, конечно, более неудобны, но должны иметь дело с чем-нибудь, что можно удаленно передать в виде html.
Златовласка

Тор, hxselectхорошо выглядит, обязательно изучу его подробнее. Спасибо.
TechJack

@goldilocks: hxnormalizeзаботится о не правильно сформированных html / xml файлах.
Tokland

5

Если rubyдоступно, вы можете сделать следующее

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

где fileваш входной HTML-файл. Команда выполняет Ruby однострочно. Во-первых, он читает все строки fileи соединяет их со строкой readlines.join. Затем из строки она выбирает что - нибудь между (но не включая) <tr>и <\/tr>что один символ или более независимо от символов новой строки [/(?<=<tr>).+(?=<\/tr>)/m]. Затем он удаляет любую строку <tr>или </tr>строку gsub(/<\/?tr>/, "")(это необходимо для обработки вложенных trтегов). Наконец, он печатает строку puts.

Вы сказали , что HTML - парсер не является оправданным для вас , но это очень простой в использовании Nokogiri с , rubyи это делает команду проще.

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

-rnokogiriгрузы Нокогири. Nokogiri::HTML(readlines.join)читает все строки file. xpath("//tr")выбирает каждый trэлемент и map { |e| e.content }выбирает содержимое для каждого элемента, то есть то, что находится между <tr>и </tr>.


1

grep

Чтобы извлечь содержимое из trтега в несколько строк, xargsсначала пропустите его , например:

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

Чтобы вернуть только внутренний HTML, используйте:

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

Проверьте синтаксис для perlreрасширенных шаблонов .

Примечание: для более быстрой работы вы можете рассмотреть, ripgrepкакой из них имеет сходный синтаксис.


он распечатал более приятный вид без xargs, пригодился для поиска встроенного JavaScript с помощью egrep -o "<script. *? </ script>"
Эндрю

0

pup

Пример использования pup(который использует селекторы CSS ):

pup -f myfile.html tr

Чтобы напечатать только текст без тегов, использование: pup -f myfile.html tr text{}.

Вот несколько примеров с curl:

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

xpup

Пример использования xpupдля разбора HTML / XML (который поддерживает XPath):

xpup -f myfile.html "//tr"

0

если это просто быстрый список <tr>s, это может помочь:

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

ура

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.