Bagaimana grep memutuskan bahwa suatu file adalah biner?


8

Saya memiliki file teks utf-8 besar yang sering saya cari grep. Baru-baru ini grepmulai melaporkan bahwa itu adalah file biner. Saya dapat terus mencarinya grep -a, tetapi saya bertanya-tanya perubahan apa yang membuatnya memutuskan bahwa file tersebut sekarang biner.

Saya memiliki salinan dari bulan lalu di mana file tidak lagi terdeteksi sebagai biner, tetapi tidak praktis bagi diffmereka karena mereka berbeda pada> 20.000 baris.

file mengidentifikasi file saya sebagai

Teks UTF-8 Unicode Bahasa Inggris, dengan garis yang sangat panjang

Bagaimana saya dapat menemukan karakter / garis / dll. di file saya yang memicu perubahan ini?


Pertanyaan serupa, non-duplikat 19907 mencakup kemungkinan NUL tetapi grep -Pc '[\x00-\x1F]'mengatakan bahwa saya tidak memiliki NUL atau perusak kontrol ANSI lainnya.


Saya akan mencoba ini dalam urutan ini: 1. Jalankan dengan strace / ltrace untuk memeriksa input apa yang menyebabkan pesan 'biner' itu. Periksa sumber grep dan bacalah
ott--

@uru: Saya menggunakan gnu grep, tetapi jika Anda memiliki jawaban untuk beberapa versi lain, saya akan tertarik juga.
Charles

Aneh. Saya memiliki file yang saya tahu berisi nuldan beberapa Esc. Saya mencoba menangkap mereka. Saya dapat menemukan escs ( \x1B), tetapi nultidak pernah muncul. Tes yang diberikan di atas menunjukkan 1, untuk baris yang berisi Escs, tetapi tidak ada untuk rentang apa pun yang tidak mengandung \x1B. Saya tidak akan percaya tes itu. Coba grep -zc .sebagai gantinya (harus lebih dari jumlah nuls dalam file Anda). (Juga, Anda mungkin lebih baik menggunakan [[:cntrl:]].)
muru

Coba juga: sed -z 's/.*\(....\)$/\1/' foo | od -cuntuk melihat beberapa karakter sebelum NUL(jika ada), yang dapat membawa Anda ke masalah.
muru

@muru: saya sedtidak memiliki -zpilihan: sed: invalid option -- 'z'.
Charles

Jawaban:


2

Tampaknya ada karakter null dalam file. (Ditampilkan ^ @ biasanya) Saya memasukkan berbagai karakter kontrol ke file teks (seperti delete, ^ ?, misalnya), dan hanya karakter null yang menyebabkan grep mempertimbangkannya biner. Ini hanya diuji untuk grep. Perintah less dan diff, misalnya, mungkin memiliki metode yang berbeda. Kontrol karakter secara umum tidak muncul kecuali dalam biner. Pengecualian adalah karakter spasi: baris baru (^ M), tab (^ I), formfeed (^ L), tab vertikal (^ K), dan kembali (^ J).

Namun, karakter asing, seperti huruf Arab atau Cina, bukan ascii standar, dan mungkin dapat dikacaukan dengan karakter kontrol. Mungkin itu sebabnya itu hanya karakter nol.

Anda dapat mengujinya sendiri dengan memasukkan karakter kontrol ke dalam file teks menggunakan vim editor teks. Masuk saja ke mode insert, tekan control-v, dan kemudian control character.


2

Implementasi grep modern yang khas hanya akan mendeklarasikan file "biner" jika ada nul byte di dalamnya. Ada lagi yang harus beres.

Saya tidak dapat berbicara untuk implementasi grep yang Anda gunakan ...


1

Kesalahan penyandian menurut mbrlen () juga membuat GNU grep 2.24 menganggapnya sebagai biner

Misalnya:

export LC_CTYPE='en_US.UTF-8'
printf 'a\x80' | grep 'a'

karena \x80tidak bisa menjadi byte pertama dari titik Unicode UTF-8: https://en.wikipedia.org/wiki/UTF-8#Description

Ini adalah satu-satunya kemungkinan lain selain itu NUL.

grepInterpretasi kode sumber GNU yang mengarah ke kesimpulan ini: Apa yang membuat grep menganggap file sebagai biner?

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.