sed regex remove caracteres especiais

sed regex remove caracteres especiais

Eu tenho um arquivo com diversas strings que vêm de um texto formatado em HTML, então elas possuem algumas sequências HTML que não ficam bem em uma interface de console. Aqui está um exemplo:

Text1™
[Text®2]
Text:3

O que estou tentando é remover tudo entre & e ; então o texto pode ser lido novamente, como o seguinte:

Text1
Text2
Text3

Na verdade, estou tentando usar sed para remover os caracteres extras:

sed 's#&*;##g' <file>

O problema é que ele apenas remove o ; das cadeias de texto.

A questão então é: como a expressão regex deve ser codificada para remover a cadeia extra:&#[1-9]+;

Responder1

Sua expressão regular

sed 's#&*;##g' <file>

não faz o que você pensa que faz. O *caractere é um multiplicador que indica que o caractere anterior é repetido 0 ou mais vezes. O caractere anterior é &, então isso corresponderia, por exemplo, &&&;e ;( &é escrito 0 vezes antes ;! Isso é o que corresponde em seus casos de teste), mas não o que você deseja neste caso.

Você precisa especificar "qualquercaractere" antes do multiplicador, que é representado por um único ponto, ..

$ echo 'Text&#58;3' | sed 's#&.*;##g'
Text3

Esse foi o primeiro problema. O segundo é o conceito da chamada correspondência "ganancioso": sedverá a primeira &e depois tentará combinar a maior string possível. Se você tiver várias entidades HTML em uma única linha, isso seria um problema, pois:

$ echo 'Text&#58;3 and some more text &aring; and end' | sed 's#&.*;##g'
Text and end

Se quiser ver uma correção no sedcontexto, você pode procurar o caractere final da entidade correspondendo a qualquer número de "não ;" antes de um fechamento ;fazendo:

$ echo 'Text&#58;3 and some more text &aring; and end' | sed 's#&[^;]*;##g'
Text3 and some more text  and end

Você ainda terá problemas com usos legítimos do sinal de e comercial ( &) no texto (bem, &amp;é o uso "legítimo" real, mas o mundo real nem sempre é tão analisável quanto o ideal) e correspondência demais, mas isso explica por que sedestá se comportando dessa maneira.

Responder2

Não é melhor substituir os códigos pelos caracteres reais?

echo 'Text1&#8482;
&#91;Text&#174;2&#93;
Text&#58;3' | perl -C -pe 's/&#([^;]*)/chr$1/eg'

Saída:

Text1™;
[;Text®;2];
Text:;3

informação relacionada