HTMLテーブルからデータを抽出するBASHスクリプトを作成しようとしています。以下は、データを抽出する必要があるテーブルの例です。
_<table border=1>
<tr>
<td><b>Component</b></td>
<td><b>Status</b></td>
<td><b>Time / Error</b></td>
</tr>
<tr><td>SAVE_DOCUMENT</td><td>OK</td><td>0.406 s</td></tr>
<tr><td>GET_DOCUMENT</td><td>OK</td><td>0.332 s</td></tr>
<tr><td>DVK_SEND</td><td>OK</td><td>0.001 s</td></tr>
<tr><td>DVK_RECEIVE</td><td>OK</td><td>0.001 s</td></tr>
<tr><td>GET_USER_INFO</td><td>OK</td><td>0.143 s</td></tr>
<tr><td>NOTIFICATIONS</td><td>OK</td><td>0.001 s</td></tr>
<tr><td>ERROR_LOG</td><td>OK</td><td>0.001 s</td></tr>
<tr><td>SUMMARY_STATUS</td><td>OK</td><td>0.888 s</td></tr>
</table>
_
そして、BASHスクリプトが次のように出力するようにします。
_SAVE_DOCUMENT OK 0.475 s
GET_DOCUMENT OK 0.345 s
DVK_SEND OK 0.002 s
DVK_RECEIVE OK 0.001 s
GET_USER_INFO OK 4.465 s
NOTIFICATIONS OK 0.001 s
ERROR_LOG OK 0.002 s
SUMMARY_STATUS OK 5.294 s
_
どうやるか?
これまでsedを使ってみましたが、使い方がよくわかりません。テーブルのヘッダー(コンポーネント、ステータス、時間/エラー)_grep "<tr><td>
_を使用してgrepで除外したため、次の解析(sed)では_<tr><td>
_で始まる行のみが選択されます。これは私が使用したものです:sed 's@<\([^<>][^<>]*\)>\([^<>]*\)</\1>@\2@g'
しかし、_<tr>
_タグはまだ残っており、文字列を分離しません。言い換えると、このスクリプトの結果は次のとおりです。
_<tr>SAVE_DOCUMENTOK0.406 s</tr>
_
私が取り組んでいるスクリプトの完全なコマンドは次のとおりです。
_cat $FILENAME | grep "<tr><td>" | sed 's@<\([^<>][^<>]*\)>\([^<>]*\)</\1>@\2@g'
_
一緒に行く (g)awk
、それは可能です:-)、ここに解決策があります、しかし注意してください:それはあなたが投稿した正確なhtmlテーブルフォーマットでのみ動作します。
awk -F "</*td>|</*tr>" '/<\/*t[rd]>.*[A-Z][A-Z]/ {print $3, $5, $7 }' FILE
ここで実際の動作を見ることができます: https://ideone.com/zGfLe
いくつかの説明:
-F
入力フィールドセパレータを正規表現(tr
またはtd
の開始タグまたは終了タグのいずれか)に設定します
次に、それらのタグと少なくとも2つのupercasseフィールドに一致する行でのみ機能します
次に、必要なフィールドを出力します。
HTH
Bash xpath
(XML :: XPath Perlモジュール)を使用して、そのタスクを非常に簡単に実行できます。
xpath -e '//tr[position()>1]' test_input1.xml 2> /dev/null | sed -e 's/<\/*tr>//g' -e 's/<td>//g' -e 's/<\/td>/ /g'
これを行うには多くの方法がありますが、ここに1つあります。
grep '^<tr><td>' < $FILENAME \
| sed \
-e 's:<tr>::g' \
-e 's:</tr>::g' \
-e 's:</td>::g' \
-e 's:<td>: :g' \
| cut -c2-
-e 's:^ ::'
の代わりにもっとsed(1)(cut -c2-
)を使用して先頭のスペースを削除することもできますが、cut(1)は使用しませんそれに値する限り多くの愛を得る。また、バックスラッシュは書式設定のためだけにあります。バックスラッシュを削除して1つのライナーを取得するか、そのままにして、すぐに改行が続くことを確認できます。
基本的な戦略は、理解できない正規表現構文の1つの山で一度にすべてを実行しようとするのではなく、HTMLを1つずつゆっくりと引き離すことです。
シェルパイプラインを使用してHTMLを解析することは、これまでで最善のアイデアではありませんが、HTMLが非常に特殊な形式であることがわかっている場合は、それを行うことができます。バリエーションがある場合は、Perl、Ruby、Python、さらにはCの実際のHTMLパーサーを使用したほうがよいでしょう。
html2text
コマンドを使用して、column
を介して列をフォーマットできます。例:
$ html2text table.html | column -ts'|'
Component Status Time / Error
SAVE_DOCUMENT OK 0.406 s
GET_DOCUMENT OK 0.332 s
DVK_SEND OK 0.001 s
DVK_RECEIVE OK 0.001 s
GET_USER_INFO OK 0.143 s
NOTIFICATIONS OK 0.001 s
ERROR_LOG OK 0.001 s
SUMMARY_STATUS OK 0.888 s
次に、そこからさらに解析します(例:cut
、awk
、ex
)。
マルチプラットフォームのWebスクレイピングCLIに基づくソリューションxidel
およびXQuery:
xidel -s --xquery 'for $tr in //tr[position()>1] return join($tr/td, " ")' file
サンプル入力を使用すると、次のようになります。
SAVE_DOCUMENT OK 0.406 s
GET_DOCUMENT OK 0.332 s
DVK_SEND OK 0.001 s
DVK_RECEIVE OK 0.001 s
GET_USER_INFO OK 0.143 s
NOTIFICATIONS OK 0.001 s
ERROR_LOG OK 0.001 s
SUMMARY_STATUS OK 0.888 s
説明:
XQueryクエリfor $tr in //tr[position()>1] return join($tr/td, " ")
は、ループ内の2番目の要素(position()>1
、ヘッダー行をスキップする)から始まるtr
要素を処理し、子td
要素($tr/td
)の値をと結合します。区切り文字としての単一のスペース。
-s
はxidel
をサイレントにします(ステータス情報の出力を抑制します)。
html2text
は抽出されたデータのdisplayに便利ですが、マシンで解析可能な出力を提供することは重要です、残念ながら:
html2text file | awk -F' *\\|' 'NR>2 {gsub(/^\||.\b/, ""); $1=$1; print}'
Awkコマンドは、デフォルトで\b
が出力する非表示のhtml2text
ベース(バックスペースベース)のシーケンスを削除し、|
によって行をフィールドに解析してから、スペースをセパレーターとして出力します(スペースはAwkのデフォルトの出力フィールドセパレーターです。たとえば、タブに変更するには、-v OFS='\t'
を使用します)。
注:ソースでバックスペースシーケンスを抑制するために-nobs
を使用することは、notオプションです。これは、パディングに使用されるデフォルトで非表示の_
インスタンスと実際の_
文字を区別できないためです。データ。
注:html2text
は常に|
を列区切り文字として使用しているように見えるため、上記は、抽出されるdataに|
インスタンスがない場合にのみ堅牢に機能します。
Ex editor (Vimの一部)を使用して、HTMLタグを削除することでファイルを解析できます。例:
$ ex -s +'%s/<[^>]\+>/ /g' +'v/0/d' +'wq! /dev/stdout' table.html
SAVE_DOCUMENT OK 0.406 s
GET_DOCUMENT OK 0.332 s
DVK_SEND OK 0.001 s
DVK_RECEIVE OK 0.001 s
GET_USER_INFO OK 0.143 s
NOTIFICATIONS OK 0.001 s
ERROR_LOG OK 0.001 s
SUMMARY_STATUS OK 0.888 s
HTMLタグなしでファイル全体を印刷することによる短いバージョンは次のとおりです。
$ ex +'%s/<[^>]\+>/ /g|%p' -scq! table.html
説明:
%s/<[^>]\+>/ /g
-[〜#〜] s [〜#〜]すべてのHTMLタグを空のスペースに置き換えます。v/0/d
-[〜#〜] d [〜#〜]0
のないすべての行を削除します。wq! /dev/stdout
-[〜#〜] q [〜#〜]uitsエディターおよびwバッファを標準出力に書き込みます。