GNU grep 2.24 RTFS
Conclusão: 2 e 2 casos apenas:
NUL
, por exemplo printf 'a\0' | grep 'a'
erro de codificação de acordo com o C99 mbrlen()
, por exemplo:
export LC_CTYPE='en_US.UTF-8'
printf 'a\x80' | grep 'a'
porque \x80
não pode ser o primeiro byte de um ponto Unicode UTF-8 : UTF-8 - Descrição | en.wikipedia.org
Além disso, como mencionado por Stéphane Chazelas O que faz o grep considerar um arquivo como binário? | Unix e Linux Stack Exchange , essas verificações são feitas apenas até a primeira leitura do buffer com o comprimento TODO.
Somente até a primeira leitura do buffer
Portanto, se ocorrer um erro de codificação ou NUL no meio de um arquivo muito grande, ele poderá ser recebido de qualquer maneira.
Eu imagino que isso seja por razões de desempenho.
Por exemplo: isso imprime a linha:
printf '%10000000s\n\x80a' | grep 'a'
mas isso não:
printf '%10s\n\x80a' | grep 'a'
O tamanho real do buffer depende de como o arquivo é lido. Por exemplo, compare:
export LC_CTYPE='en_US.UTF-8'
(printf '\n\x80a') | grep 'a'
(printf '\n'; sleep 1; printf '\x80a') | grep 'a'
Com o sleep
, a primeira linha é passada para o grep, mesmo que tenha apenas 1 byte, porque o processo entra no modo de espera ea segunda leitura não verifica se o arquivo é binário.
RTFS
git clone git://git.savannah.gnu.org/grep.git
cd grep
git checkout v2.24
Localize onde a mensagem de erro stderr está codificada:
git grep 'Binary file'
Nos leva 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);
Se essas variáveis foram bem nomeadas, chegamos basicamente à conclusão.
encoding_error_output
O grepping rápido para encoding_error_output
mostra que o único caminho de código que pode modificá-lo passa por buf_has_encoding_errors
:
clen = mbrlen (p, buf + size - p, &mbs);
if ((size_t) -2 <= clen)
return true;
então apenas man mbrlen
.
nlines_first_null e nlines
Inicializado como:
intmax_t nlines_first_null = -1;
nlines = 0;
portanto, quando um nulo é encontrado, 0 <= nlines_first_null
torna-se verdadeiro.
TODO quando pode nlines_first_null < nlines
ser falso? Eu fiquei com preguiça
POSIX
Não define opções binárias grep - pesquisa um padrão em um arquivo | pubs.opengroup.org e GNU grep não o documentam, então o RTFS é a única maneira.
--null-data
pode ser útil seNUL
for o delimitador.