GNU grep 2.24 RTFS
Conclusión: solo 2 y 2 casos:
NUL
, p.ej printf 'a\0' | grep 'a'
error de codificación según el C99 mbrlen()
, por ejemplo:
export LC_CTYPE='en_US.UTF-8'
printf 'a\x80' | grep 'a'
porque \x80
no puede ser el primer byte de un punto Unicode UTF-8 : UTF-8 - Descripción | en.wikipedia.org
Ademá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:
printf '%10000000s\n\x80a' | grep 'a'
pero esto no:
printf '%10s\n\x80a' | grep 'a'
El tamaño real del búfer depende de cómo se lea el archivo. Por ejemplo, comparar:
export LC_CTYPE='en_US.UTF-8'
(printf '\n\x80a') | grep 'a'
(printf '\n'; sleep 1; printf '\x80a') | grep 'a'
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
git clone git://git.savannah.gnu.org/grep.git
cd grep
git checkout v2.24
Encuentre dónde está codificado el mensaje de error stderr:
git grep 'Binary file'
Nos lleva a /src/grep.c
:
if (!out_quiet && (encoding_error_output
|| (0 <= nlines_first_null && nlines_first_null < nlines)))
{
printf (_("Binary file %s matches\n"), filename);
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 por buf_has_encoding_errors
:
clen = mbrlen (p, buf + size - p, &mbs);
if ((size_t) -2 <= clen)
return true;
entonces solo man mbrlen
.
nlines_first_null y nlines
Inicializado como:
intmax_t nlines_first_null = -1;
nlines = 0;
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.
--null-data
puede ser útil siNUL
es el delimitador.