txt ファイルに次の内容があります:
<ol><li><b><a href="/page1/Mark_Yato" title="Mark Yato">Mark Yato</a> ft. MarkAm & <a href="/page1/Giv%C4%93on" title="Givēon">Givēon</a> - <a href="/page1/Mark_Yato:Thuieo" title="Mark Yato:Thuieo">Thuieo</a> (7)</b></li>
<li><b><a href="/page1/The_Central" title="The Central">The Central</a> - <a href="/page1/The_Central:AHTIOe oie" title="The Central:AHTIOe oie">AHTIOe oie</a> (7)</b></li>
<li><b><a href="/page1/Taa_Too_A" title="Taa Too A">Taa Too A</a> - <a href="/page1/Taa_Too_A:ryhwtyw w" title="Taa Too A:ryhwtyw w">ryhwtyw w</a> (8)</b></li>
次のように出力するようにしています:
Mark Yato ft. MarkAm & Givēon - Thuieo
The Central - AHTIOe oie
Taa Too A - ryhwtyw w
これを実現するために、私は「<」、「>」、およびそれらの間のすべてを削除して、取得しようとしているリストだけが残るようにしてみようと考えました。
すでに次の sed コマンドを試しました:
sed 's/<[^()]*>//g'
しかし、出力は次のようになります。
(7)
(7)
(8)
何が間違っているのでしょうか。また、sed コマンドを修正したり、awk に変換したりすれば、より使いやすくなるのでしょうか。
答え1
正規表現でマークアップを解析することは悪名高い問題。
サンプル データでは問題になりませんが、山括弧がタグ属性、コメント、その他の場所に出現し、からに一致する正規表現が<
信頼>
できない場合があります。
マークアップ パーサーを実装するツールに頼る必要があります。
例えば、パンドック(バージョン >= 2.8) サンプル データ (不足している</ol>
タグを追加しない) を使用します。
$ pandoc -f html -t plain file
Mark Yato ft. MarkAm & Givēon - Thuieo (7)
The Central - AHTIOe oie (7)
Taa Too A - ryhwtyw w (8)
その後、この出力を通常のテキストとして簡単に後処理し、空行やその他の不要な部分を削除できます。
$ pandoc -f html -t plain file |
sed -e '/^$/d' -e 's/[[:blank:]]*([[:digit:]]*)$//'
Mark Yato ft. MarkAm & Givēon - Thuieo
The Central - AHTIOe oie
Taa Too A - ryhwtyw w
バージョン2.8より前では、フォーマットpandoc
で出力を生成する際に強調されたテキストをすべて大文字に変換していましたplain
。<b>
リスト項目のタグがこの動作を引き起こします(詳細は変更履歴または関連する専念GitHub でご覧ください。
実際の入力データに応じて、回避策markdown
としてpandoc
、 の入力形式を明示的に使用することもできます。
pandoc -f markdown -t plain file
pandoc
または、自動的にデフォルトで ( pandoc -t plain file
)になるものを考慮して、暗黙的に指定します。
答え2
もうすぐ完了です。正規表現の一致は「貪欲」なので、パターン内では終了>
文字が許可されないことをパターンに伝える必要があります。言い換えると、[^()]*
パターン内の部分は「貪欲」にできる限り多くのテキストと一致します。パターンのこの部分から終了を除外するようにパターンに指示しないと>
、正規表現が使用する開始<
と終了は>
、HTML の観点からは必ずしもペアになっているものとはかぎりません。
代わりにこれを使用してください:
sed -e 's/<[^>]*>//g'
これにより、正規表現は、両端に<
and があり、中央にorがある大きなテキスト ブロックではなく、すべての HTML タグを削除するようになります。>
<
>
答え3
php
すべての HTML タグを削除し、HTML エンティティを通常の文字に戻すには、次のようにします。
$ <file php -r 'echo htmlspecialchars_decode(strip_tags(file_get_contents("php://stdin")), ENT_HTML5);'
Mark Yato ft. MarkAm & Givēon - Thuieo (7)
The Central - AHTIOe oie (7)
Taa Too A - ryhwtyw w (8)
さらに、行末の(
、 、 つ以上の数字、および の後に続く空白 (スペース、タブ) と閉じ文字を削除します。)
sed
$ <file php -r 'echo htmlspecialchars_decode(strip_tags(file_get_contents("php://stdin")), ENT_HTML5);' |
sed 's/[[:blank:]]*([[:digit:]][[:digit:]]*)$//'
Mark Yato ft. MarkAm & Givēon - Thuieo
The Central - AHTIOe oie
Taa Too A - ryhwtyw w
答え4
使用方法xmlstarlet
:
xmlstarlet fo -H file |
xmlstarlet sel -E latin1 -t -v '//li' -nl 2>/dev/null |
xmlstarlet unesc | sed 's/ [^ ]*$//'
これは、xmlstarlet
HTML フラグメントを整形式の HTML ドキュメントに変換するために使用します (1 番目のコマンド)。次に、各ノードの値を抽出します(2 番目のコマンド)。最後に、HTML エンティティ (例)li
をデコードします。最後のコマンドは、各行の最後のスペースの後のすべてを削除します (括弧内の数字は出力の一部ではありません)。&
sed
質問の文書に与えられた出力:
Mark Yato ft. MarkAm & Givēon - Thuieo
The Central - AHTIOe oie
Taa Too A - ryhwtyw w