Removendo todos os caracteres não-ascii de um fluxo de trabalho (arquivo)

10

Como eu removerei todos os caracteres não ascii de um arquivo? Haveria um comando específico para realizar isso?

grep --colour='auto' -P -n'[^\x00-\x7]' /usr/local/...

Acredito que isso encontre os caracteres no fluxo de trabalho, mas como removerei todas as instâncias dos caracteres em questão?

    
por Mizole Ni 15.10.2018 / 12:01

3 respostas

19

Os caracteres ASCII são caracteres na faixa de 0 a 177 (octal) inclusive .

Para excluir caracteres fora desse intervalo em um arquivo, use

tr -dc '
tr -dc '
tr -dc '
tr -dc '%pre%-7' <file >newfile && mv newfile file
-7' <file >newfile
-7' <file >newfile && mv newfile file
-7' <file >newfile

O comando tr é um utilitário que funciona em caracteres únicos , seja substituindo-os com outros caracteres únicos (transliteração), excluindo-os ou compactando execuções do mesmo caractere em um único caractere.

O comando acima leria de file e gravaria o conteúdo modificado em newfile . A opção -d para tr faz o utilitário excluir caracteres (em vez de transliterá-los) e -c faz com que ele considere caracteres fora do intervalo especificado (em vez de dentro).

Para substituir o arquivo original pelo modificado, use

%pre%

Isso renomeia o novo arquivo para o nome do arquivo antigo após tr ter sido concluído com sucesso. Se tr não for concluído com sucesso, seja porque não foi possível ler o arquivo original ou não gravar no novo arquivo, o arquivo original será mantido inalterado.

    
por 15.10.2018 / 12:07
10

com perl

perl -pi -e 's/[^[:ascii:]]//g'
    
por 15.10.2018 / 12:23
8

Se tudo que você precisa é de um regex: [\x00-\x7F] que você poderia aplicar a vários utilitários:

<file LC_ALL=C.UTF8   sed   's/[^\o0-\o177]//g'
<file   awk   '{print gensub(/[^\x0-\x7f]/,"","g")}'
<file   perl  -pe 's/[^[:ascii:]]//g;'
<file   tr    -dc '
<file LC_ALL=C.UTF8   sed   's/[^\o007-\o015\o040-\o176]//g'
<file   awk   '{print gensub(/[^\x07-\x0d\x020-\x7e]/,"","g")}'
<file   perl  -pe 's/[^\x{7}-\x{d}\x{20}-\x{7e}]//g;'
<file   tr    -dc '--6'
-7'

Entenda que sed, awk e perl esperam "arquivos de texto", conforme definido no Unix. Todos funcionam bem neste caso. Mas especificamente, o awk adiciona uma nova linha à direita (se existia no arquivo de origem ou não). O tr foi projetado para funcionar com qualquer tipo de arquivo.

No entanto, o NUL ( [\x07-\x0d\x20-\x7e] ) não é um caractere válido em um arquivo de texto POSIX e deve ser evitado:

The lines do not contain NUL characters...

De fato, muitos caracteres de controle podem gerar problemas em alguns casos.
Então, provavelmente você precisa de \a\b\t\n\v\f\r

<file LC_ALL=C.UTF8   sed   's/[^[:space:][:print:]]//g'
<file   awk    '{print gensub(/[^\x07-\x0d\x020-\x7e]/,"","g")}'
<file   perl   -pe 's/[^[:space:][:print:]]//g;'
<file   tr     -dc '[:space:][:print:]'

O intervalo 7-13 (em decimal) é [^[:space:][:print:]] (similar because it doesn't include (em ordem).
Um intervalo similar (provavelmente mais portátil) poderia ser escrito como %code% \ a \ b 'bell e backspace).

<file LC_ALL=C.UTF8   sed   's/[^\o0-\o177]//g'
<file   awk   '{print gensub(/[^\x0-\x7f]/,"","g")}'
<file   perl  -pe 's/[^[:ascii:]]//g;'
<file   tr    -dc '
<file LC_ALL=C.UTF8   sed   's/[^\o007-\o015\o040-\o176]//g'
<file   awk   '{print gensub(/[^\x07-\x0d\x020-\x7e]/,"","g")}'
<file   perl  -pe 's/[^\x{7}-\x{d}\x{20}-\x{7e}]//g;'
<file   tr    -dc '--6'
-7'

Relacionados: Regex qualquer caractere ASCII Solução de Perl
Arquivo de texto Posix

    
por 15.10.2018 / 14:05