Tengo algunos volcados de base de datos de un sistema Windows en mi caja. Son archivos de texto. Estoy usando cygwin para atravesarlos. Estos parecen ser archivos de texto sin formato; Los abro con editores de texto como el bloc de notas y el wordpad y se ven legibles. Sin embargo, cuando corro grep sobre ellos, dirá binary file foo.txt matches
.
He notado que los archivos contienen algunos NUL
caracteres ascii , que creo que son artefactos del volcado de la base de datos.
Entonces, ¿qué hace que grep considere que estos archivos son binarios? El NUL
personaje? ¿Hay una bandera en el sistema de archivos? ¿Qué necesito cambiar para que grep me muestre las coincidencias de línea?
--null-data
puede ser útil siNUL
es el delimitador.Respuestas:
Si hay un
NUL
carácter en cualquier parte del archivo, grep lo considerará como un archivo binario.Puede haber una solución como esta
cat file | tr -d '\000' | yourgrep
para eliminar todos los valores nulos primero y luego buscar a través del archivo.fuente
-a
/--text
, al menos con GNU grep.NUL
(¿probablemente porque llama a printf de C y le da la línea coincidente?). En dicho sistemagrep cmd .sh_history
, a devolverá tantas líneas vacías como líneas que coincidan con 'cmd', ya que cada línea de sh_history tiene un formato específico con unNUL
al comienzo de cada línea. (pero su comentario "al menos sobre GNU grep" probablemente se haga realidad. No tengo uno a mano en este momento para probar, pero espero que manejen esto muy bien)grep
en cygwin consideraba binario porque tenía un guión largo (0x96) en lugar de un guión ASCII regular / menos (0x2d). Supongo que esta respuesta resolvió el problema del OP, pero parece que está incompleto.grep -a
trabajó para mi:fuente
Puede utilizar la
strings
utilidad para extraer el contenido del texto de cualquier archivo y luego canalizarla a través degrep
, por ejemplo:strings file | grep pattern
.fuente
GNU grep 2.24 RTFS
Conclusión: solo 2 y 2 casos:
NUL
, p.ejprintf 'a\0' | grep 'a'
error de codificación según el C99
mbrlen()
, por ejemplo:porque
\x80
no puede ser el primer byte de un punto Unicode UTF-8 : UTF-8 - Descripción | en.wikipedia.orgAdemás, como lo menciona Stéphane Chazelas ¿Qué hace que grep considere que un archivo es binario? El | Unix y Linux Stack Exchange , esas comprobaciones solo se realizan hasta la primera lectura de búfer de longitud TODO.
Solo hasta la primera lectura del búfer
Por lo tanto, si se produce un error de codificación o NUL en el medio de un archivo muy grande, de todos modos podría aparecer grep.
Me imagino que esto es por razones de rendimiento.
Por ejemplo: esto imprime la línea:
pero esto no:
El tamaño real del búfer depende de cómo se lea el archivo. Por ejemplo, comparar:
Con el
sleep
, la primera línea se pasa a grep incluso si solo tiene 1 byte porque el proceso se detiene, y la segunda lectura no comprueba si el archivo es binario.RTFS
Encuentre dónde está codificado el mensaje de error stderr:
Nos lleva a
/src/grep.c
:Si esas variables estaban bien nombradas, básicamente llegamos a la conclusión.
encoding_error_output
Grepping rápido para
encoding_error_output
muestra que la única ruta de código que puede modificarlo pasa porbuf_has_encoding_errors
:entonces solo
man mbrlen
.nlines_first_null y nlines
Inicializado como:
así que cuando se encuentra un nulo se
0 <= nlines_first_null
convierte en verdad.TODO cuando puede
nlines_first_null < nlines
ser falso? Me volví flojo.POSIX
No define las opciones binarias grep: busca en un archivo un patrón | pubs.opengroup.org , y GNU grep no lo documenta, por lo que RTFS es la única forma.
fuente
(printf '\n\0y') | grep y
con(printf '\n'; sleep 1; printf '\0y') | grep y
por ejemplo.export LC_CTYPE='en_US.UTF-8'
que en mi ejemplo, o algo más? Buf read: ejemplo increíble, agregado a la respuesta. Obviamente has leído la fuente más que yo, me recuerda a esos hackers koans "El estudiante estaba iluminado" :-)Grep de repente vio uno de mis archivos de texto como binario:
La solución fue convertirlo usando
iconv
:fuente
0xFC
hexadecimal, por lo que fuera del rango que grep esperaría para utf8 (hasta0x7F
). Verifique con printf 'a \ x7F' | grep 'a' como Ciro describe arriba.El archivo
/etc/magic
o/usr/share/misc/magic
tiene una lista de secuencias que el comandofile
usa para determinar el tipo de archivo.Tenga en cuenta que el binario puede ser una solución alternativa. A veces, los archivos con codificación extraña también se consideran binarios.
grep
en Linux tiene algunas opciones para manejar archivos binarios como--binary-files
o-U / --binary
fuente
mbrlen()
. Ejemplo e interpretación de la fuente en: unix.stackexchange.com/a/276028/32558Uno de mis alumnos tuvo este problema. Hay un error
grep
enCygwin
. Si el archivo tiene caracteres que no son Ascii,grep
y véaloegrep
como binario.fuente
En realidad, respondiendo a la pregunta "¿Qué hace que grep considere que un archivo es binario?", Puede usar
iconv
:En mi caso, había caracteres españoles que aparecían correctamente en los editores de texto, pero grep los consideraba binarios;
iconv
la salida me señaló los números de línea y columna de esos caracteresEn el caso de los
NUL
caracteres,iconv
los considerará normales y no imprimirá ese tipo de salida, por lo que este método no es adecuado.fuente
Yo tuve el mismo problema. Solía
vi -b [filename]
ver los caracteres añadidos. Encontré los personajes de control^@
y^M
. Luego, en vi escriba:1,$s/^@//g
para eliminar los^@
caracteres. Repita este comando para^M
.Advertencia: para obtener los caracteres de control "azules", presione Ctrl+ y vluego Ctrl+ Mo Ctrl+ @. Luego guardar y salir vi.
fuente