BashでHTMLを解析する
私はウェブページからすべての画像をコピーするプロセスを持っています。以前は xmllint を使ってこのプロセスを実行していましたが、これは XML または HTML ファイルを処理し、指定したエントリを出力します。しかし、サーバーホストプロバイダーがシステムをアップグレードしたとき、xmllint を含めませんでした。だから、HTML ページから画像のリストを抽出する別の方法を見つける必要がありました。実際、これを Bash で行うことができます。
あなたはBashがデータファイルを解析できないと思うかもしれませんが、少し考えれば解析できます。Bashは、それ以前の他のUNIXシェルと同様に、組み込みのreadステートメントを介してファイルから一度に1行ずつ解析できます。
デフォルトでは、read文はデータの行をスキャンし、それをフィールドに分割します。通常、readはスペースとタブを使用してフィールドを分割し、新しい行が各行を終了しますが、内部フィールド区切り文字を設定することでこの動作を変更できます。
IFS値と行末区切り文字
-d
).
HTMLファイルをreadを使って解析するには、設定します。
IFS大なり記号(>)と区切り記号を小なり記号(<)に変換します。Bash が行をスキャンするたびに、次の <(HTML タグの開始)までパースし、そのデータを各 >(HTML タグの終了)で分割します。このサンプルコードは、入力行を受け取り、データを TAG と VALUE 変数に分けます。
local IFS='>'
read -d '<' TAG VALUE
これはどのように機能するのか探索してみましょう。この簡単なHTMLファイルを考えてみてください:
<img src="logo.png"
/>
some text</p>
最初にreadがこのファイルを解析するとき、最初の<記号で停止します。<がこのサンプル入力の最初の文字であるため、Bashは空の文字列を見つけます。その結果として、TAGとVALUEの文字列も空です。しかし、私の使い方には問題ありません。
次にBashが入力を読み込むと、img src="logo.png"↲ />↲がaltの前に改行と共に得られ、次の行の<記号の手前で停止します。次にreadが行を>記号で分割し、TAGにはimg src="logo.png"↲ /が、VALUEには空の改行が残ります。
3回目にreadがHTMLファイルを解析すると、p>some textを取得します。Bashは文字列を>で分割し、TAGにはpが含まれ、VALUEにはsome textが含まれます。
今、readの使い方が分かったので、Bashを使って長いHTMLファイルを簡単にパースできます。データをreadを使ってパースするために、xmlgetnextと呼ばれるBash関数から始めましょう。これはスクリプト内で何度も行うことになるからです。私の関数をxmlgetnextと名付けたのは、これはLinuxのxmllintプログラムの置き換えであることを思い出させるためですが、htmlgetnextと名付けることも簡単にできました。
xmlgetnext () {
local IFS='>'
read -d '<' TAG VALUE
}
今、その xmlgetnext 関数を呼び出して、HTMLファイルを解析します。これが私の完全な htmltags スクリプトです:
#!/bin/sh
print a list of all html tags
xmlgetnext () {
local IFS='>'
read -d '<' TAG VALUE
}
cat $1 | while xmlgetnext ; do echo $TAG ; done
最後の行が鍵です。これは、xmlgetnextを使用してファイルをループし、HTMLを解析し、TAGエントリのみを出力します。そして、echoが標準フィールドセパレーターでどのように動作するかにより、img src="logo.png"↲ /のような改行を含む行は、img src="logo.png" /として1行に印刷されます。
画像のリストだけを取得するために、このスクリプトの出力をgrepで処理して、行の先頭にimgタグがある行だけを印刷するようにしています。

