Verwenden Sie awk oder sed, um alles zwischen < > zu entfernen

Verwenden Sie awk oder sed, um alles zwischen < > zu entfernen

Ich habe folgendes in einer txt-Datei:

<ol><li><b><a href="/page1/Mark_Yato" title="Mark Yato">Mark Yato</a> ft. MarkAm &amp; <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>

und versuche, es wie folgt auszugeben:

Mark Yato ft. MarkAm & Givēon - Thuieo
The Central - AHTIOe oie
Taa Too A - ryhwtyw w

Um dies zu erreichen, dachte ich, ich würde versuchen, „<“, „>“ und alles dazwischen zu entfernen, sodass nur die Liste übrig bleibt, die ich abrufen möchte.

Ich habe bereits den folgenden Sed-Befehl ausprobiert:

sed 's/<[^()]*>//g'

aber dies gibt nur Folgendes aus:

(7)
(7)
(8)

Was mache ich falsch und wie kann ich den Sed-Befehl reparieren oder in awk übersetzen, wenn er dafür besser geeignet ist?

Antwort1

Das Parsen von Markup mit regulären Ausdrücken istnotorisch problematisch.

Obwohl dies bei Ihren Beispieldaten kein Problem darstellt, können spitze Klammern in Tag-Attributen, Kommentaren und möglicherweise an anderen Stellen erscheinen, wodurch reguläre Ausdrücke, die von <bis übereinstimmen, >unzuverlässig werden.

Sie sollten auf Tools zurückgreifen, die einen Markup-Parser implementieren.

Verwenden Sie beispielsweisepandoc(Version >= 2.8) mit Ihren Beispieldaten (ohne das fehlende </ol>Tag hinzuzufügen):

$ 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)

Sie können diese Ausgabe dann problemlos als normalen Text nachbearbeiten, um Leerzeilen und andere unerwünschte Teile zu entfernen:

$ 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

Beachten Sie, dass vor Version 2.8 pandocjeder hervorgehobene Text in Großbuchstaben umgewandelt wurde, wenn die Ausgabe im plainFormat generiert wurde. Das <b>Tag in Ihren Listenelementen löste dieses Verhalten aus (mehr dazu imÄnderungsprotokolloder die entsprechendenbegehenauf GitHub).

Abhängig von Ihren tatsächlichen Eingabedaten könnte eine Problemumgehung darin bestehen, markdowndas pandocEingabeformat von entweder explizit zu verwenden:

pandoc -f markdown -t plain file

oder implizit, wenn man bedenkt, dass dies die pandocautomatische Standardeinstellung ( pandoc -t plain file) ist.

Antwort2

Sie sind fast am Ziel – Regex-Übereinstimmungen sind „gierig“, daher müssen Sie dem Muster mitteilen, dass das schließende >Zeichen innerhalb des Musters nicht zulässig ist. Anders ausgedrückt: Der [^()]*Teil innerhalb des Musters wird „gierig“ mit so viel Text übereinstimmen, wie möglich. Wenn Sie dem Muster nicht mitteilen, das schließende Zeichen >aus diesem Teil des Musters auszuschließen, sind die vom Regex verwendeten öffnenden <und schließenden Zeichen >nicht unbedingt diejenigen, die aus HTML-Sicht gepaart sind.

Verwenden Sie stattdessen Folgendes:

sed -e 's/<[^>]*>//g'

Dies zwingt den regulären Ausdruck, jedes HTML-Tag zu löschen, nicht einen größeren Textblock, der am Ende sowie <in der Mitte „ und“ hat.><>

Antwort3

Sie können phpalle HTML-Tags entfernen und die HTML-Entitäten wieder in normale Zeichen umwandeln:

$ <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)

Um zusätzlich Leerzeichen (Leerzeichen, Tabulatoren) zu entfernen, auf die ein öffnendes (, gefolgt von einer oder mehreren Zahlen und einem schließenden Zeichen )an den mit endenden Zeilen folgt 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

Antwort4

Verwendung von xmlstarlet:

xmlstarlet fo -H file |
xmlstarlet sel -E latin1 -t -v '//li' -nl 2>/dev/null |
xmlstarlet unesc | sed 's/ [^ ]*$//'

Dies dient xmlstarletdazu, das HTML-Fragment in ein wohlgeformtes HTML-Dokument umzuwandeln (der 1. Befehl). Anschließend extrahiert es den Wert jedes liKnotens (der 2. Befehl). Schließlich dekodiert es alle HTML-Entitäten ( &amp;zum Beispiel). Der letzte sedBefehl löscht einfach alles nach dem letzten Leerzeichen in jeder Zeile (es gibt Zahlen in Klammern, die nicht Teil der Ausgabe sein sollten).

Die Ausgabe des in der Frage enthaltenen Dokuments:

Mark Yato ft. MarkAm & Givēon - Thuieo
The Central - AHTIOe oie
Taa Too A - ryhwtyw w

verwandte Informationen