GNU grep 2,24 RTFS
Висновок: лише 2 та 2 справи:
NUL
, напр printf 'a\0' | grep 'a'
помилка кодування відповідно до C99 mbrlen()
, наприклад:
export LC_CTYPE='en_US.UTF-8'
printf 'a\x80' | grep 'a'
тому що \x80
не може бути першим байтом точки Unicode UTF-8 : UTF-8 - Опис | en.wikipedia.org
Крім того, як згадував Стефан Шазелас. Що змушує греп вважати файл двійковим? | У Unix та Linux Stack Exchange ці перевірки проводяться лише до першого зчитування буфера довжиною TODO.
Лише до першого зчитування буфера
Отже, якщо в середині дуже великого файлу трапляється помилка NUL або кодування, вона все одно може бути зірвана.
Я думаю, це з міркувань продуктивності.
Наприклад: це друкує рядок:
printf '%10000000s\n\x80a' | grep 'a'
але це не так:
printf '%10s\n\x80a' | grep 'a'
Фактичний розмір буфера залежить від того, як читається файл. Наприклад, порівняйте:
export LC_CTYPE='en_US.UTF-8'
(printf '\n\x80a') | grep 'a'
(printf '\n'; sleep 1; printf '\x80a') | grep 'a'
З sleep
, перший рядок передається в grep, навіть якщо він лише 1 байт, оскільки процес переходить у режим сну, а другий читання не перевіряє, чи файл є бінарним.
RTFS
git clone git://git.savannah.gnu.org/grep.git
cd grep
git checkout v2.24
Знайдіть, де закодоване повідомлення про помилку stderr:
git grep 'Binary file'
Веде нас до /src/grep.c
:
if (!out_quiet && (encoding_error_output
|| (0 <= nlines_first_null && nlines_first_null < nlines)))
{
printf (_("Binary file %s matches\n"), filename);
Якщо ці змінні були добре названі, ми в основному дійшли висновку.
encoding_error_output
Швидке схвалення encoding_error_output
показує, що єдиний шлях коду, який може змінити його, проходить buf_has_encoding_errors
:
clen = mbrlen (p, buf + size - p, &mbs);
if ((size_t) -2 <= clen)
return true;
то просто man mbrlen
.
nlines_first_null і nlines
Ініціалізовано як:
intmax_t nlines_first_null = -1;
nlines = 0;
тому коли знайдено нуль 0 <= nlines_first_null
стає істинним.
TODO, коли коли- nlines_first_null < nlines
небудь може бути помилковим? Я лінивий.
POSIX
Grep не визначає бінарні параметри - пошук у файлі за шаблоном | pubs.opengroup.org , і GNU grep не документує його, тому RTFS - єдиний спосіб.
--null-data
може бути корисним, якщоNUL
є роздільником.