GNU grep 2.24 RTFS
Wniosek: tylko 2 i 2 przypadki:
NUL
np printf 'a\0' | grep 'a'
błąd kodowania zgodnie z C99 mbrlen()
, np .:
export LC_CTYPE='en_US.UTF-8'
printf 'a\x80' | grep 'a'
ponieważ \x80
nie może być pierwszym bajtem punktu Unicode UTF-8 : UTF-8 - Opis | en.wikipedia.org
Co więcej, jak wspomniał Stéphane Chazelas. Co sprawia, że grep uważa plik za plik binarny? | Wymiana stosów Unix i Linux , kontrole są wykonywane tylko do pierwszego odczytu bufora o długości TODO.
Tylko do pierwszego odczytanego bufora
Jeśli więc wystąpi błąd NUL lub błąd kodowania w środku bardzo dużego pliku, może on zostać i tak grepowany.
Wyobrażam sobie, że dzieje się tak ze względu na wydajność.
Np .: drukuje linię:
printf '%10000000s\n\x80a' | grep 'a'
ale to nie:
printf '%10s\n\x80a' | grep 'a'
Rzeczywisty rozmiar bufora zależy od sposobu odczytu pliku. Np. Porównaj:
export LC_CTYPE='en_US.UTF-8'
(printf '\n\x80a') | grep 'a'
(printf '\n'; sleep 1; printf '\x80a') | grep 'a'
W przypadku sleep
pierwszego wiersza przechodzi do grep, nawet jeśli ma on tylko 1 bajt długości, ponieważ proces przechodzi w tryb uśpienia, a drugi odczyt nie sprawdza, czy plik jest binarny.
RTFS
git clone git://git.savannah.gnu.org/grep.git
cd grep
git checkout v2.24
Znajdź, gdzie jest zakodowany komunikat o błędzie Stderr:
git grep 'Binary file'
Prowadzi nas do /src/grep.c
:
if (!out_quiet && (encoding_error_output
|| (0 <= nlines_first_null && nlines_first_null < nlines)))
{
printf (_("Binary file %s matches\n"), filename);
Jeśli te zmienne były dobrze nazwane, zasadniczo doszliśmy do wniosku.
encoding_error_output
Szybkie grepping dla encoding_error_output
pokazuje, że jedyna ścieżka kodu, która może go modyfikować, przechodzi buf_has_encoding_errors
:
clen = mbrlen (p, buf + size - p, &mbs);
if ((size_t) -2 <= clen)
return true;
to po prostu man mbrlen
.
nlines_first_null i nlines
Zainicjowany jako:
intmax_t nlines_first_null = -1;
nlines = 0;
więc po znalezieniu wartości null 0 <= nlines_first_null
staje się prawdą.
DO ZROBIENIA, kiedy może nlines_first_null < nlines
być fałsz? Zrobiłem się leniwy
POSIX
Nie definiuje opcji binarnych grep - wyszukaj plik w poszukiwaniu wzorca | pubs.opengroup.org , a GNU grep tego nie dokumentuje, więc RTFS jest jedynym sposobem.
--null-data
może być przydatny, jeśliNUL
jest separatorem.