私の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'
<
これにより、正規表現は末尾と間の大きなテキストブロックを削除するのではなく、各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)
追加のスペース(スペース、タブ)、開始、(
1つ以上の数字、および次の末尾)
の行の末尾を削除するには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文書に変換するために使用されます(最初のコマンド)。次に、各ノードの値を抽出しますli
(2番目のコマンド)。最後に、HTMLエンティティ(&
例:)をデコードします。最後sed
のコマンドは、単に各行の最後のスペースの後のすべての項目を削除します(括弧内の数字は出力の一部にしてはいけません)。
質問に提供された文書の出力:
Mark Yato ft. MarkAm & Givēon - Thuieo
The Central - AHTIOe oie
Taa Too A - ryhwtyw w