HTML を scraping したかったのだが、対象箇所が1箇所だと Ruby や Python を持ち出して parse するのも面倒なので bash で済ませたいなと。
しかし sed でやるのは煩雑なので、もっと手軽な方法がないものかと「
bash html parse」でググってみたところ xmllint が使えそうなことが分かった。
ところが、UTF-8 で書かれたマルチバイト文字を含む HTML を xmllint に食わせて xpath を処理させてみたところ、マルチバイトコードが上手く処理出来ず、以下のように属性値は数値文字参照(numeric character reference)に、要素の内容は一応 UTF-8 っぽいのだがおかしなコードに文字化けしてしまう。
$ read html <<<'<!DOCTYPE html><html><head><meta name="title" content="こんにちは世界"></head><body><p>こんにちは世界</p></body></html>'
$ echo $html
<!DOCTYPE html><html><head><meta name="title" content="こんにちは世界"></head><body><p>こんにちは世界</p></body></html>
$ echo "$html" | xmllint --xpath '//meta' --html -
<meta name="title" content="こんにちは世界"/>
$ echo こんにちは世界|xxd
00000000: e381 93e3 8293 e381 abe3 81a1 e381 afe4 ................
00000010: b896 e795 8c0a ......
$ echo "$html" | xmllint --xpath 'string(//p)' --html - | xxd
00000000: c3a3 c281 c293 c3a3 c282 c293 c3a3 c281 ................
00000010: c2ab c3a3 c281 c2a1 c3a3 c281 c2af c3a4 ................
00000020: c2b8 c296 c3a7 c295 c28c 0a ...........
$ echo "$html" | xmllint --xpath 'string(//p)' --html - | nkf -g
UTF-8
ヘルプを見ると --encode ENCODING ってオプションがあったので、試しに --encoding utf-8 を与えてみたが効果が見られなかった。