FULLALLGOL 技術ノート

grep が 0 件を返すとき、無いのは「その文字列」とは限らない

2026-08-31

ある社内ツールのソースから関数名を grep したら 0 件だった。
ファイルは存在するし、その関数は確かに書かれている。エラーも警告も出ない。ただ 0 件。

結論から言うと、そのファイルには生の NUL バイトが 1 個入っていた。

NUL が 1 個あると、grep はそのファイルを読まない

greprg も、NUL を含むファイルをバイナリと判定する。
そして無音でスキップする。返ってくる 0 件は「その文字列が無い」ではなく
「そのファイルを見ていない」を意味している。

厄介なのは、他のツールは普通に読めることだ。
エディタでも sed でも中身は見える。嘘をつくのは検索ツールだけなので、
「grep で引けない=存在しない」と読み違える。

このケースでは、区切り文字として NUL を選んだこと自体は正しい判断だった。
扱うデータに絶対に出現しない値なので、キーの衝突が起きない。
問題は書き方のほうで、ソースにバイトを直接埋めたのが事故の原因だった。

バイトを直接埋めるとそのファイルは検索から消える。
バックスラッシュ + u0000 のエスケープ表記で書けば、
文字列としての値は同じままバイナリ判定だけが消える。挙動は変わらない。
変わるのは、検索ツールから見えるかどうかだけだ。

直すときにエディタの一括置換を使ってはいけない。不可視文字は目視で確認できないので、
別の制御文字に化けても気づけない。「NUL がちょうど 1 個」をコードでアサートしてから
バイト指定で置換する。

余談だが、この事故を説明するために書いたメモ自身にも NUL が 2 個混ざっていた。
つまりそのメモも grep で引けなかった。汚染は原因ファイルの中で完結しない。

文字化けの検出では、検出器のほうが化ける

同じ「ツールが嘘をつく」系で、文字コードまわりにもいくつか型がある。
以下は Windows と Git Bash を併用していた時期に踏んだものだ。

症状実際に起きていること
置換文字を PCRE で探して 0 件シェル環境によって日本語パターンのマッチが不安定
画面上の文字列が化けて見えるファイル実体は正常。表示層だけが化けている
置換ツールが対象を見つけられない入力したバイト列が実体と一致していない
標準出力に出した瞬間に落ちるcp932 のコンソールが置換文字を出力できない

とくに危ないのは 2 行目だ。**表示が化けているだけのファイルを「壊れている」と判断して打ち直すと、
そこで初めて本物の破損が入る**。健全なファイルを自分の手で壊すことになる。

対処はどれも同じ方向を向いている。

共通する形

4 つとも、症状は「静かに間違った答えが返る」だ。落ちてくれるほうがまだ親切で、
0 件や「変更なし」は正常な結果の顔をしている

検出器が 0 件と言ったとき、「無い」のか「見ていない」のかを区別する手段を必ず 1 つ持つ。
区別できないなら、その 0 件は情報量ゼロだ。

まとめ