Новичок борется с grep, sed, awk для фильтрации html

Я начинающий пользователь Linux, пытаясь научить себя использованию Linux-инструментов в установке cygwin. Я решил составить проект, чтобы попытаться научить себя основам сценариев оболочки и одновременно выполнить какое-то личное образование. Мой первоначальный проект состоял в том, чтобы сохранить html-страницы от каждого победителя премии Сахарова в папке и написать сценарий, который обрабатывал бы все текстовые файлы html и возвращал имя, год, рождение и смерть в переносном формате и страну происхождения. Из-за определенных несоответствий в форматировании даты (18 июля 1918 г. по 23 января 1938 г.), а также невозможности справиться с мертвыми людьми против живых людей без даты смерти или выяснить, как сообщить компьютеру о том, как распознавать названия стран без ручного перечисления из всех стран, я в основном отказался от этого проекта.

Теперь я просто пытаюсь вернуть год, имя и страну происхождения каждого получателя из таблицы html, взятой со страницы Википедии в прессе Сахарова .

Итак, учитывая следующий пример html:

<tr> <td>1988</td> <td><span style="display:none;">Mandela, Nelson</span><span class="vcard"><span class="fn"><a href="/wiki/Nelson_Mandela" title="Nelson Mandela">Nelson Mandela</a></span></span></td> <td><a href="/wiki/South_Africa" title="South Africa">South Africa</a></td> <td>Anti-apartheid activist and later President of South Africa</td> <td><sup id="cite_ref-twentyyears_5-0" class="reference"><a href="#cite_note-twentyyears-5"><span>[</span>5<span>]</span></a></sup></td> </tr> <tr> <td>1988</td> <td><span style="display:none;">Marchenko, Anatoly</span><span class="vcard"><span class="fn"><a href="/wiki/Anatoly_Marchenko" title="Anatoly Marchenko">Anatoly Marchenko</a></span></span> (posthumously)</td> <td><a href="/wiki/Soviet_Union" title="Soviet Union">Soviet Union</a></td> <td>Soviet dissident, author and humans rights activist</td> <td><sup id="cite_ref-twentyyears_5-1" class="reference"><a href="#cite_note-twentyyears-5"><span>[</span>5<span>]</span></a></sup></td> </tr> 

каков наилучший способ вернуть только год, имя и страну происхождения каждого получателя? Прямо сейчас я подумываю о написании awk-скрипта, который возвращает все, что не соответствует / <*> /, но это не совсем то, что я хочу. Может ли кто-нибудь дать мне несколько указателей или идеи о том, как выбрать имена, год и страны? Или, по крайней мере, некоторые книги с лучшими и более управляемыми пробными проблемами, чем те, которые я мог бы придумать сам? Ничего из этого не звучало необоснованно, когда я начал …

3 Solutions collect form web for “Новичок борется с grep, sed, awk для фильтрации html”

Как уже упоминалось, regex не подходит для разбора html . Подобно другому ответу синтаксического анализа, вы можете сделать однострочный Ruby, такой как следующий, чтобы сделать это для вас. Обратите внимание, что для него требуется Nokogiri, который вы можете установить как драгоценный камень ( sudo gem install nokogiri ).

 ruby -rnokogiri -e 'Nokogiri::HTML(readlines.join).css("tr").each { |tr| tr.xpath(".//td").take(3).each { |td| puts td.content } }' sample.html 

Он читает данный файл, в этом случае sample.html, получает все три элемента, и для каждого такого элемента он печатает содержимое первых трех элементов td .

Для вашего образца он будет выводить:

 1988
 Мандела, НельсонНелсон Мандела
 Южная Африка
 1988
 Марченко, АнатолийАнатолий Марченко (посмертно)
 Советский Союз

Проблема заключается в строках, которые содержат имена дважды, например (отформатированные, чтобы их было легче читать)

 <td> <span style="display:none;">Mandela, Nelson</span> <span class="vcard"><span class="fn"> <a href="/wiki/Nelson_Mandela" title="Nelson Mandela">Nelson Mandela</a> </span> </span> </td> 

в котором имя первое в span с style="display:none;" а затем снова в другом span . Я не уверен, как извлечь только имя, которое не входит в элемент со style="display:none; (Я нашел https://stackoverflow.com/q/6096327/789593 и https://stackoverflow.com / q / 11602077/789593, но они не описывают правильный tecnique. Возможно, кто-то может придумать исправление через http://nokogiri.org/Nokogiri/XML/Node.html ?)

Я создал пакет node.js, который можно использовать здесь: gumba . Это своего рода awk, sed замена.

поэтому в вашем примере это будет работать следующим образом:

 cat file.html | gumba "stripTags()" 

который выводит:

 1988 Mandela, NelsonNelson Mandela South Africa Anti-apartheid activist and later President of South Africa [5] 1988 Marchenko, AnatolyAnatoly Marchenko (posthumously) Soviet Union Soviet dissident, author and humans rights activist [5] 

Хотя здесь я думаю, что лучше не использовать oneliners, а фактически писать скрипт на любом языке, который вы знаете.

 sed -rn ' /<tr>/ { n s#<td>([^<]*)</td>#\1# h n s#<td><span[^>]*>([^<]*)</span>.*#\1# H n s#<td><a href=[^>]*>([^<]*)</a>.*#\1# H x;p } ' file 1988 Mandela, Nelson South Africa 1988 Marchenko, Anatoly Soviet Union 
  • sed многострочная рекурсивная подстановка шаблона
  • Игнорировать разделитель, присутствующий внутри кавычек
  • Делайте более длинные строки из подстрок, сохраняя новую строку между каждой строкой
  • Как извлечь журналы между двумя отметками времени
  • подсчеты совпадений и несоответствий
  • Единая команда, берущая две строки для извлечения строки между ними, например, 'tr' (без выражений)
  • Получить серийный номер из Показать инвентарь
  • Удалить строки, содержащие X в определенном столбце .csv
  • Добавление последовательных символов для дублирования слов в соответствии с порядком их появления
  • Исключить все строки с конкретными строчными символами в текстовом файле unix
  • Замена определенного номера в файлах unix
  • Linux и Unix - лучшая ОС в мире.