Identificación y eliminación de caracteres nulos en UNIX

98

Tengo un archivo de texto que contiene caracteres nulos no deseados (ASCII NUL \0). Cuando intento verlo, viveo ^@símbolos intercalados en texto normal. Cómo puedo:

  1. ¿Identifica qué líneas del archivo contienen caracteres nulos? Intenté grepping para \0y \x0, pero esto no funcionó.

  2. ¿Eliminar los caracteres nulos? Ejecutar stringsen el archivo lo limpió, pero me pregunto si esta es la mejor manera.

dogbane
fuente
1
Este tipo de pregunta probablemente pertenece a SuperUser.com
Olivier Lalonde
2
De hecho, esta cuestión está en superuser.com: superuser.com/questions/75130/how-to-remove-ths-symbol-with-vim
jn

Respuestas:

130

Yo usaría tr:

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

Si se pregunta si la redirección de entrada en medio de los argumentos del comando funciona, lo hace. La mayoría de las conchas se reconocer y tratar con E / S de cambio de dirección ( <, >, ...) en cualquier lugar de la línea de comandos, en realidad.

Puntiagudo
fuente
y un "archivo diff-with-nulls file-without-nulls" debería mostrarme qué líneas tenían caracteres nulos? Trae mucho más de lo esperado.
dogbane
10
En realidad, creo que debería serlo, tr -d '\000' < file-with-nulls > file-without-nullsya que <es parte de la funcionalidad de la tubería de shell y no tr.
Mikael S
9
La mayoría de los shells reconocerán y tratarán con <o> en cualquier parte de la cadena de argumentos, en realidad. También me sorprendió.
pra
1
+1 Para el uso de redirección de entrada en lugar de cat |. Una solución fina y limpia que resolvió mi problema.
Krzysztof Jabłoński
4
@Pointy '\ 000' se usa en lugar de '\ 0' en la especificación POSIX opengroup para tr. Esa es una buena razón para preferirlo
Harold Fischer
67

Utilice el siguiente comando sed para eliminar los caracteres nulos en un archivo.

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

esta solución edita el archivo en su lugar, importante si el archivo todavía se está utilizando. al pasar -i'ext 'se crea una copia de seguridad del archivo original con el sufijo' ext 'agregado.

rekha_sri
fuente
6
Nota: En FreeBSD (y creo que también Mac OS X), sed -i requiere una extensión en el siguiente argumento, pero puede estar vacío. En esos sistemas, agregar una '', como en: sed -i '' 's/\x0//g "$FILE".
Tim Čas
1
Este es un orden de magnitud más rápido que trpara mí
diachedelic
Para mí, al usar Git para Windows y $ sed --version-> sed (GNU sed) 4.7, tuve que usar la siguiente invocación para obtener un archivo de respaldo llamado example.csv.bak:sed -i.bak 's/\x0//g' example.csv
Andrew Keeton
1
@ Tim, como lo hiciste genial, solo te perdiste uno 'así que debería ser sed -i' '' s / \ x0 // g 'some_file.xml
Darko
@Darko Así lo hice. ¡Ups!
Tim Čas
22

Una gran cantidad de caracteres NUL no deseados, digamos uno cada dos bytes, indica que el archivo está codificado en UTF-16 y que debe usar iconvpara convertirlo a UTF-8.

Ignacio Vázquez-Abrams
fuente
1
Me quedé sin espacio en disco mientras mi aplicación se estaba registrando. Esto resulta en estos personajes.
dogbane
Por ejemplo, funciona con este comando: iconv -f UTF-16 -t UTF-8 file.
djule5
7

Descubrí lo siguiente, que imprime qué líneas, si las hay, tienen caracteres nulos:

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

Además, un volcado octal puede indicarle si hay nulos:

od file-with-nulls | grep ' 000'
dogbane
fuente
5

Si las líneas del archivo terminan con \ r \ n \ 000, entonces lo que funciona es eliminar el \ n \ 000 y luego reemplazar el \ r con \ n.

tr -d '\n\000' <infile | tr '\r' '\n' >outfile
wwmbes
fuente
PD. Si se encuentra en un shell DOS de Windows, puede obtener las versiones GNU / win32 de los comandos Unix de Sourceforge.net. Los utilizo todo el tiempo. Echa un vistazo a "od", el comando de volcado octal para analizar lo que hay en un archivo ...
wwmbes
2

A continuación, se muestra un ejemplo de cómo eliminar caracteres NULL usando ex(en el lugar):

ex -s +"%s/\%x00//g" -cwq nulls.txt

y para varios archivos:

ex -s +'bufdo!%s/\%x00//g' -cxa *.txt

Para la recursividad, puede usar la opción globbing **/*.txt (si es compatible con su shell).

Útil para la creación de scripts ya que sed su -iparámetro es una extensión BSD no estándar.

Consulte también: ¿Cómo comprobar si el archivo es un archivo binario y leer todos los archivos que no lo son?

Kenorb
fuente
1

Solía:

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

para deshacerse de los ceros en el archivo.

logisec
fuente
0

Me enfrenté al mismo error con:

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

Resolví el problema cambiando la codificación a utf-16

f=cd.open(filePath,'r','utf-16')
Ming Young
fuente