Identificando e removendo caracteres nulos no UNIX


98

Eu tenho um arquivo de texto contendo caracteres nulos indesejados (ASCII NUL, \0). Quando tento visualizá-lo vi, vejo ^@símbolos intercalados em texto normal. Como posso:

  1. Identificar quais linhas no arquivo contêm caracteres nulos? Tentei usar o grep para \0e \x0, mas não funcionou.

  2. Remover os caracteres nulos? Executando stringsno arquivo limpei, mas eu só estou me perguntando se esta é a melhor maneira?


1
Esse tipo de pergunta provavelmente pertence ao SuperUser.com
Olivier Lalonde,

2
Na verdade, esta pergunta está em superuser.com: superuser.com/questions/75130/how-to-remove-ths-symbol-with-vim
jrb

Respostas:


130

Eu usaria tr:

tr < file-with-nulls -d '\000' > file-without-nulls

Se você está se perguntando se o redirecionamento de entrada no meio dos argumentos do comando funciona, ele funciona. A maioria das conchas irá reconhecer e lidar com I / O redirecionamento ( <, >...) em qualquer lugar na linha de comando, na verdade.


e um "arquivo diff com nulos arquivo sem nulos" deve mostrar quais linhas têm caracteres nulos? Isso traz de volta muito mais do que o esperado.
dogbane

10
Na verdade, eu acredito que deveria ser, tr -d '\000' < file-with-nulls > file-without-nullsjá que <faz parte da funcionalidade do shell pipe e não tr.
Mikael S

9
A maioria dos shells irá reconhecer e lidar com <ou> em qualquer lugar na string do argumento, na verdade. Me surpreendeu também.
pra

1
+1 Para uso de redirecionamento de entrada em vez de cat |. Uma solução boa e limpa que resolveu meu problema.
Krzysztof Jabłoński

4
@Pointy '\ 000' é usado no lugar de '\ 0' na especificação de grupo aberto POSIX para tr. Essa é uma boa razão para preferir
Harold Fischer

67

Use o seguinte comando sed para remover os caracteres nulos em um arquivo.

sed -i 's/\x0//g' null.txt

esta solução edita o arquivo no local, importante se o arquivo ainda estiver sendo usado. passando -i'ext 'cria um backup do arquivo original com o sufixo' ext 'adicionado.


6
Nota: No FreeBSD (e acredito que também no Mac OS X), sed -i requer uma extensão no próximo argumento, mas pode estar vazia. Nesses sistemas, adicione um '', como em: sed -i '' 's/\x0//g "$FILE".
Tim Čas 01 de

1
Esta é uma ordem de magnitude mais rápida do que trpara mim
diachedélico

Para mim, usando Git para Windows e $ sed --version-> sed (GNU sed) 4.7, tive que usar a seguinte invocação para obter um arquivo de backup chamado example.csv.bak:sed -i.bak 's/\x0//g' example.csv
Andrew Keeton

1
@ Tim. Como você fez muito bem, faltou apenas um 'então deveria ser sed -i' '' s / \ x0 // g 'algum_arquivo.xml
Darko

@Darko Então eu fiz. Opa.
Tim Čas

22

Um grande número de caracteres NUL indesejados, digamos um a cada dois bytes, indica que o arquivo está codificado em UTF-16 e que você deve usar iconvpara convertê-lo em UTF-8.


1
Eu fiquei sem espaço em disco enquanto meu aplicativo estava registrando. Isso resultou nesses personagens.
dogbane,

Por exemplo, ele funciona usando este comando: iconv -f UTF-16 -t UTF-8 file.
djule5

7

Eu descobri o seguinte, que imprime quais linhas, se houver, têm caracteres nulos:

perl -ne '/\000/ and print;' file-with-nulls

Além disso, um despejo octal pode informar se há nulos:

od file-with-nulls | grep ' 000'

5

Se as linhas do arquivo terminarem com \ r \ n \ 000, o que funciona é excluir \ n \ 000 e substituir \ r por \ n.

tr -d '\n\000' <infile | tr '\r' '\n' >outfile

PS. Se você estiver em um shell DOS do Windows, poderá obter as versões GNU / win32 dos comandos Unix no Sourceforge.net. Eu os uso o tempo todo. Verifique "od" o comando octal dump para analisar o que está em um arquivo ...
wwmbes


1

Eu usei:

recode UTF-16..UTF-8 <filename>

para se livrar dos zeros no arquivo.


0

Eu enfrentei o mesmo erro com:

import codecs as cd
f=cd.open(filePath,'r','ISO-8859-1')

Resolvi o problema mudando a codificação para utf-16

f=cd.open(filePath,'r','utf-16')
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.