Use awk ou sed para remover tudo entre < >

Use awk ou sed para remover tudo entre < >

Eu tenho o seguinte em um arquivo 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>

e estou tentando fazer com que a saída seja a seguinte:

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

Para conseguir isso, pensei em tentar remover '<', '>' e tudo entre eles, para que fique apenas a lista que estou tentando obter.

Já tentei o seguinte comando sed:

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

mas isso está gerando apenas o seguinte:

(7)
(7)
(8)

O que estou fazendo de errado e como posso corrigir o comando sed ou traduzi-lo para awk se for melhor usá-lo para isso?

Responder1

Analisar marcação com expressões regulares énotoriamente problemático.

Embora não seja um problema com seus dados de amostra, colchetes angulares podem aparecer em atributos de tags, comentários e possivelmente em outros lugares, tornando expressões regulares que correspondem de <a >não confiáveis.

Você deve recorrer a ferramentas que implementem um analisador de marcação.

Por exemplo, usandopandoc(versão >= 2.8) com seus dados de amostra (sem adicionar a </ol>tag ausente):

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

Você pode então facilmente pós-processar esta saída como texto normal para remover linhas vazias e outras partes indesejadas:

$ 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

Observe que, antes da versão 2.8, pandocera usado para converter qualquer texto enfatizado em letras maiúsculas ao gerar saída no plainformato. A <b>tag nos itens da sua lista acionaria esse comportamento (mais sobre isso noregistro de alteraçõesou o relevantecomprometer-seno GitHub).

Dependendo dos seus dados de entrada reais, uma solução alternativa poderia ser usar o formato de entrada markdownas pandoc', explicitamente:

pandoc -f markdown -t plain file

ou implicitamente, considerando que é o pandocpadrão automático ( pandoc -t plain file).

Responder2

Você está quase lá - as correspondências de regex são "gananciosos", então você precisa informar ao padrão que o >caractere de fechamento não é permitido dentro do padrão. Dito de outra forma, a [^()]*parte dentro do padrão corresponderá ao máximo de texto possível "avidamente". Se você não instruir o padrão a excluir o fechamento >desta parte do padrão, a abertura <e o fechamento >que o Regex usa não serão necessariamente aqueles que estão emparelhados do ponto de vista HTML.

Use isto em vez disso:

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

Isso força a regex a excluir todas as tags HTML, e não um bloco maior de texto que possui <e >no final, bem como <ou >no meio.

Responder3

Você poderia usar phppara remover todas as tags HTML e converter as entidades HTML de volta aos caracteres normais:

$ <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 remover adicionalmente espaços em branco (espaços, tabulações) seguidos por uma abertura (, seguida por um ou mais números e um fechamento )nas linhas que terminam com 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

Responder4

Usando xmlstarlet:

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

Isto é usado xmlstarletpara converter o fragmento HTML em um documento HTML bem formado (o primeiro comando). Em seguida, extrai o valor de cada linó (2º comando). Finalmente, ele decodifica qualquer entidade HTML ( &amp;por exemplo). O comando final sedapenas exclui qualquer coisa após o último espaço em cada linha (há números entre parênteses que não deveriam fazer parte da saída).

A saída dada ao documento na pergunta:

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

informação relacionada