GNU grep 2.24 RTFS
Conclusion: 2 et 2 cas seulement:
NUL
, par exemple printf 'a\0' | grep 'a'
erreur de codage selon C99 mbrlen()
, par exemple:
export LC_CTYPE='en_US.UTF-8'
printf 'a\x80' | grep 'a'
car \x80
ne peut pas être le premier octet d'un point Unicode UTF-8 : UTF-8 - Description | en.wikipedia.org
De plus, comme l'a mentionné Stéphane Chazelas, qu'est-ce qui fait que grep considère un fichier comme étant binaire? | Unix et Linux Stack Exchange , ces vérifications ne sont effectuées que jusqu’à la première lecture de tampon de longueur TODO.
Seulement jusqu'à la première lecture du tampon
Ainsi, si une erreur NUL ou une erreur d'encodage se produit au milieu d'un fichier très volumineux, il se peut qu'il s'agisse d'une erreur.
J'imagine que c'est pour des raisons de performance.
Ex: ceci imprime la ligne:
printf '%10000000s\n\x80a' | grep 'a'
mais cela ne veut pas:
printf '%10s\n\x80a' | grep 'a'
La taille réelle de la mémoire tampon dépend de la façon dont le fichier est lu. Par exemple comparer:
export LC_CTYPE='en_US.UTF-8'
(printf '\n\x80a') | grep 'a'
(printf '\n'; sleep 1; printf '\x80a') | grep 'a'
Avec la sleep
, la première ligne est transmise à grep même si elle ne dure qu'un octet, car le processus passe en veille, et la deuxième lecture ne vérifie pas si le fichier est binaire.
RTFS
git clone git://git.savannah.gnu.org/grep.git
cd grep
git checkout v2.24
Recherchez où le message d'erreur stderr est codé:
git grep 'Binary file'
Nous amène à /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 ces variables étaient bien nommées, nous en sommes essentiellement à la conclusion.
encoding_error_output
La recherche rapide pour encoding_error_output
indique que le seul chemin de code pouvant le modifier passe par buf_has_encoding_errors
:
clen = mbrlen (p, buf + size - p, &mbs);
if ((size_t) -2 <= clen)
return true;
alors juste man mbrlen
.
nlines_first_null et nlines
Initialisé comme:
intmax_t nlines_first_null = -1;
nlines = 0;
alors quand un nul est trouvé 0 <= nlines_first_null
devient vrai.
TODO quand peut-il nlines_first_null < nlines
être faux? Je suis paresseux.
POSIX
Ne définit pas les options binaires grep - recherche dans un fichier un motif | pubs.opengroup.org , et GNU grep ne le documente pas, RTFS est donc le seul moyen.
--null-data
peut être utile siNUL
est le délimiteur.