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
UTF-8 Unicodeポイントの最初のバイトにはできないためです。UTF-8-説明| en.wikipedia.org
さらに、StéphaneChazelasが述べたように、grepがファイルをバイナリと見なす理由は何ですか?| Unix&Linux Stack Exchange、これらのチェックは、TODOの長さの最初のバッファー読み取りまでのみ行われます。
最初のバッファー読み取りまでのみ
そのため、非常に大きなファイルの途中でNULまたはエンコードエラーが発生した場合、とにかくgrepされる可能性があります。
これはパフォーマンス上の理由によるものだと思います。
たとえば、次の行を出力します。
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
と、プロセスがスリープ状態になるため1バイトしかない場合でも、最初の行はgrepに渡され、2番目の行はファイルがバイナリかどうかをチェックしません。
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
クイックgrepping 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;
そのため、nullが見つかる0 <= nlines_first_null
とtrueになります。
TODOはいつnlines_first_null < nlines
偽になる可能性がありますか?怠けた。
POSIX
バイナリオプションを定義しませんgrep-パターンのファイルを検索します| pubs.opengroup.org、およびGNU grepでは文書化されていないため、RTFSが唯一の方法です。
--null-data
がNUL
区切り文字の場合に役立ちます。