Jak parsować sto plików kodu źródłowego HTML w powłoce?

23

Mam kilkaset plików kodu źródłowego HTML. Muszę wyodrębnić zawartość określonego <div>elementu z każdego z tych plików, więc mam zamiar napisać skrypt, który przejdzie przez każdy plik. Struktura elementu wygląda następująco:

<div id='the_div_id'>
  <div id='some_other_div'>
  <h3>Some content</h3>
  </div>
</div>

Czy ktoś może zasugerować metodę, za pomocą której mogę wyodrębnić div the_div_idoraz wszystkie elementy potomne i zawartość z pliku przy użyciu wiersza polecenia systemu Linux?

conorgriffin
źródło

Odpowiedzi:

27

Pakiet html-xml-utils , dostępny w większości głównych dystrybucji Linuksa, zawiera szereg narzędzi, które są użyteczne w przypadku dokumentów HTML i XML. Szczególnie przydatny w twoim przypadku jest to, że hxselectodczytuje ze standardowego wejścia i wyciąga elementy oparte na selektorach CSS. Twój przypadek użycia wyglądałby następująco:

hxselect '#the_div_id' <file

Możesz otrzymać skargę dotyczącą nieprawidłowego kształtowania danych wejściowych w zależności od tego, co je karmisz. Ta skarga dotyczy standardowego błędu i dlatego w razie potrzeby można ją łatwo zlikwidować. Alternatywą byłoby użycie pakietu HTML :: PARSER Perla; zostawię to jednak osobie z umiejętnościami Perla mniej zardzewiałymi niż moje własne.

Steven D.
źródło
1
hxselectjest bardziej wrażliwy na format wejściowy niż pup. Na przykład, ja dostaję Input is not well-formed. (Maybe try normalize?)z hxselect którym pupwłaśnie analizowania go.
AB
12

Wypróbuj pupnarzędzie wiersza polecenia do przetwarzania HTML. Na przykład:

pup '#the_div_id' < file.html
Trevor Dixon
źródło
Terrrrrrrific!
CC
4

Oto nieprzetestowany skrypt Perla, który wyodrębnia <div id="the_div_id">elementy i ich zawartość za pomocą HTML::TreeBuilder.

#!/usr/bin/env perl
use strict;
use warnings;
use HTML::TreeBuilder;
foreach my $file_name (@ARGV) {
    my $tree = HTML::TreeBuilder->new;
    $tree->parse_file($file_name);
    for my $subtree ($tree->look_down(_tag => "div", id => "the_div_id")) {
        my $html = $subtree->as_HTML;
        $html =~ s/(?<!\n)\z/\n/;
        print $html;
    }
    $tree = $tree->delete;
}

Jeśli masz alergię na Perla, Python ma HTMLParser.

PS Nie próbuj używać wyrażeń regularnych. .

Gilles „SO- przestań być zły”
źródło
1

Oto Ex jeden wiersz, aby wyodrębnić tę część z każdego pliku:

ex -s +'bufdo!/<div.*id=.the_div_id/norm nvatdggdG"2p' +'bufdo!%p' -cqa! *.html

Aby zapisać / zamienić na miejscu, zmień sekcję -cqa!na -cxai usuń %p. W przypadku rekurencyjności rozważ użycie globbing ( **/*.html).

Zasadniczo dla każdego bufora / pliku ( bufdo) wykonuje następujące działania:

  • /pattern - znajdź wzór
  • norm - zacznij symulować normalne naciśnięcia klawiszy Vi
    • n - wskocz do następnego wzoru (wymagany w trybie Ex)
    • vatd- usuń wybraną sekcję zewnętrznego znacznika (patrz: przeskakiwanie między znacznikami HTML )
    • ggdG- usuń cały bufor (odpowiednik :%d)
    • "2p - ponownie wklej poprzednio usunięty tekst

Być może niezbyt wydajny i nie POSIX ( :bufdo), ale powinien działać.

kenorb
źródło
uwaga bufdo nie jest POSIX pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html
Steven Penny