ボックスにWindowsシステムからのデータベースダンプがいくつかあります。それらはテキストファイルです。 cygwinを使用してgrepを実行しています。これらはプレーンテキストファイルのようです。メモ帳やワードパッドなどのテキストエディタで開くと読みやすくなります。ただし、grepを実行すると、binary file foo.txt matches
。
ファイルにいくつかのascii NUL
文字が含まれていることに気付きました。これはデータベースダンプからのアーティファクトだと思います。
では、grepがこれらのファイルをバイナリと見なす理由は何ですか?NUL
文字ですか?ファイルシステムにフラグがありますか?grepを取得するには何を変更する必要がありますか?行の一致を表示しますか?
コメント
回答
NUL
文字はファイル内のどこにでもあり、grepはそれをバイナリファイルと見なします。
このcat file | tr -d "\000" | yourgrep
のような回避策があります。最初にすべてnull、そして次に、ファイルを検索します。
コメント
、少なくともGNUgrepでは。
@derobert:実際、一部の(古い)システムでは、grepは行を参照しますが、その出力は最初に一致する各行を切り捨てます。 NUL
(おそらく、C 'のprintfを呼び出して、一致する行を指定するためですか?)このようなシステムでは、grep cmd .sh_history
は' cmd '、sh_historyの各行には特定の形式があり、各行の先頭にNUL
があります。 (ただし、少なくともGNU grep "に関するコメント"はおそらく実現します。私は'現在テスト用のものはありませんが、これをうまく処理できると思います)
NUL文字の存在が唯一の基準ですか?疑わしい。 'はおそらくそれよりも賢いでしょう。 Ascii 32-126の範囲外のものはすべて私の推測ですが、'確実にソースコードを確認する必要があります。
私の情報は特定のgrepインスタンスのmanページから。実装に関するあなたのコメントは有効です、ソースはドキュメントよりも優先されます。
cygwinのgrep
は、ダッシュの代わりに長いダッシュ(0x96)があったため、バイナリと見なされたファイルがありました。通常のASCIIハイフン/マイナス(0x2d)。この回答でOP 'の問題は解決したと思いますが、不完全なようです。
回答
grep -a
は私のために働いた:
$ grep --help [...] -a, --text equivalent to --binary-files=text
コメント
回答
を使用できますdiv id = “907fa53eca”>
ユーティリティを使用して、任意のファイルからテキストコンテンツを抽出し、次のようにgrep
にパイプします。strings file | grep pattern
。
コメント
回答
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-8Unicodeポイントの最初のバイトにすることはできないため: 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
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 when can nlines_first_null < nlines
間違ったことはありますか?怠け者になりました。
POSIX
バイナリオプションを定義しません grep-ファイルでパターンを検索する| pubs.opengroup.org であり、GNU grepはそれを文書化していないため、RTFSが唯一の方法です。
コメント
回答
grepによってテキストファイルの1つが突然バイナリとして表示されました:
$ file foo.txt foo.txt: ISO-8859 text
解決策は、iconv
を使用して変換することでした:
iconv -t UTF-8 -f ISO-8859-1 foo.txt > foo_new.txt
コメント
回答
ファイル/etc/magic
または/usr/share/misc/magic
には、コマンド
はファイルタイプの決定に使用します。
注意バイナリは単なるフォールバックソリューションである可能性があります。奇妙なエンコーディングのファイルもバイナリと見なされることがあります。
grep
Linuxでは--binary-files
または-U / --binary
コメント
回答
私の生徒の1人がこの問題を抱えていました。 Cygwin
のgrep
にバグがあります。ファイルにASCII以外の文字が含まれている場合、grep
およびegrep
はファイルをバイナリとして表示します。
コメント
回答
「grepがファイルをバイナリと見なす理由」という質問に実際に答えるには、iconv
を使用できます:
$ iconv < myfile.java iconv: (stdin):267:70: cannot convert
私の場合、テキストエディタに正しく表示されるスペイン語の文字がありましたが、grepはそれらをバイナリと見なしました。 iconv
の出力で、これらの文字の行番号と列番号が示されました
NUL
文字の場合、iconv
はそれらを正常と見なし、そのような出力を出力しないため、このメソッドは適切ではありません
回答
同じ問題がありました。 vi -b [filename]
を使用して追加された文字を確認しました。制御文字^@
と^M
が見つかりました。次に、viで:1,$s/^@//g
と入力して、^@
文字を削除します。 ^M
に対してこのコマンドを繰り返します。
警告:「青」の制御文字を取得するには、 Ctrl + v を押してから、 Ctrl + M <を押します。 / kbd>または Ctrl + @ 。次に、viを保存して終了します。
回答
この問題も発生しましたが、私の場合は、一致した行が長すぎます。
file myfile.txt myfile.txt: UTF-8 Unicode text, with very long lines
grep
は、多くのパターンでファイル全体を正常に処理しますが、パターンが"非常に長い行"で停止しましたBinary file myfile.txt matches
。
-a
を追加してもこの問題は解決しますが、ファイルのNULLまたはその他の無効な文字を事前に解析しても効果はありません(それ以外の場合、grepが他のパターンで完了しないことはありません)。この場合、問題のある行には25k以上の文字が含まれていました!
私が理解していないのは、grep
が行を返そうとしたときにのみ発生し、返そうとしたときではない理由です。他のパターンを探して処理しています。
--null-data
は、は区切り文字です。