Utilice awk o sed para eliminar todo lo que esté entre < >

Utilice awk o sed para eliminar todo lo que esté entre < >

Tengo lo siguiente en un archivo txt:

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

y estoy tratando de que el resultado sea el siguiente:

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

Para lograr esto, pensé en intentar eliminar '<', '>' y todo lo que hay entre ellos para que quede solo la lista que estoy tratando de obtener.

Ya probé el siguiente comando sed:

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

pero esto genera solo lo siguiente:

(7)
(7)
(8)

¿Qué estoy haciendo mal y cómo puedo arreglar el comando sed o traducirlo a awk si es mejor usarlo para eso?

Respuesta1

Analizar el marcado con expresiones regulares esnotoriamente problemático.

Si bien no es un problema con los datos de muestra, los corchetes angulares pueden aparecer en atributos de etiquetas, comentarios y posiblemente en otros lugares, lo que hace que las expresiones regulares que coinciden con no <sean >confiables.

Deberías recurrir a herramientas que implementen un analizador de marcado.

Por ejemplo, usandopandoc(versión >= 2.8) con sus datos de muestra (sin agregar la </ol>etiqueta que falta):

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

Luego podrás postprocesar fácilmente este resultado como texto normal para eliminar líneas vacías y otras partes no deseadas:

$ 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

Tenga en cuenta que, antes de la versión 2.8, pandocse utilizaba para convertir cualquier texto resaltado a mayúsculas al generar resultados en plainformato. La <b>etiqueta en los elementos de su lista desencadenaría este comportamiento (más sobre esto en elregistro de cambioso el relevantecomprometerseen GitHub).

Dependiendo de sus datos de entrada reales, una solución alternativa podría ser utilizar el formato de entrada markdownas pandoc, ya sea explícitamente:

pandoc -f markdown -t plain file

o implícitamente, considerando que es lo que pandocautomáticamente toma por defecto ( pandoc -t plain file).

Respuesta2

Ya casi has llegado: las coincidencias de expresiones regulares son "codiciosas", por lo que debes decirle al patrón que el >carácter de cierre no está permitido dentro del patrón. Dicho de otra manera, la [^()]*parte dentro del patrón coincidirá con la mayor cantidad de texto posible "con avidez". Si no le dice al patrón que excluya el cierre >de esta parte del patrón, la apertura <y el cierre >que usa Regex no son necesariamente los que están emparejados desde un punto de vista HTML.

Utilice esto en su lugar:

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

Esto obliga a la expresión regular a eliminar cada etiqueta HTML, no un bloque de texto más grande que tenga <y >en los extremos, así como <o >en el medio.

Respuesta3

Puede utilizar phppara eliminar todas las etiquetas HTML y convertir las entidades HTML a caracteres normales:

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

Para eliminar adicionalmente espacios en blanco (espacios, tabulaciones) seguidos de una apertura (, seguido de uno o más números y un cierre )en la línea que termina en 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

Respuesta4

Usando xmlstarlet:

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

Esto se utiliza xmlstarletpara convertir el fragmento HTML en un documento HTML bien formado (el primer comando). Luego extrae el valor de cada linodo (el segundo comando). Finalmente, decodifica cualquier entidad HTML ( &amp;por ejemplo). El sedcomando final simplemente elimina todo lo que hay después del último espacio en cada línea (hay números entre paréntesis que no deberían formar parte del resultado).

El resultado dado el documento en la pregunta:

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

información relacionada