it-swarm-id.com

Apa yang membuat grep menganggap file sebagai biner?

Saya memiliki beberapa dump database dari sistem Windows di komputer saya. Itu adalah file teks. Saya menggunakan cygwin untuk memahami mereka. Ini tampaknya file teks biasa; Saya membukanya dengan editor teks seperti notepad dan wordpad dan mereka terlihat terbaca. Namun, ketika saya menjalankan grep pada mereka, ia akan mengatakan binary file foo.txt matches.

Saya perhatikan bahwa file-file tersebut mengandung beberapa karakter ascii NUL, yang saya yakini adalah artefak dari dump basis data.

Jadi apa yang membuat grep menganggap file-file ini sebagai biner? Karakter NUL? Apakah ada tanda pada filesystem? Apa yang harus saya ubah untuk mendapatkan grep untuk menunjukkan kepada saya baris yang cocok?

203
user394

Jika ada karakter NUL di mana saja dalam file, grep akan menganggapnya sebagai file biner.

Mungkin ada solusi seperti ini cat file | tr -d '\000' | yourgrep untuk menghapus semua null terlebih dahulu, lalu mencari melalui file.

139
bbaja42

grep -a bekerja untuk saya:

$ grep --help
[...]
 -a, --text                equivalent to --binary-files=text
140
Plouff

Anda dapat menggunakan utilitas strings untuk mengekstraksi konten teks dari file apa pun dan kemudian menyalurkannya melalui grep, seperti ini: strings file | grep pattern.

21
holgero

GNU grep 2.24 RTFS

Kesimpulan: 2 dan 2 hanya kasus:

  • NUL, mis. printf 'a\0' | grep 'a'

  • kesalahan pengodean menurut C99 mbrlen(), mis .: .:

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

    karena \x80 tidak boleh menjadi byte pertama dari titik Unicode UTF-8: TF-8 - Deskripsi | en.wikipedia.org

Selanjutnya, seperti yang disebutkan oleh Stéphane Chazelas Apa yang membuat grep menganggap file sebagai biner? | Unix & Linux Stack Exchange , pemeriksaan tersebut hanya dilakukan hingga pembacaan buffer pertama dengan panjang TODO.

Hanya sampai buffer pertama dibaca

Jadi, jika NUL atau kesalahan penyandian terjadi di tengah file yang sangat besar, itu bisa saja diambil.

Saya membayangkan ini untuk alasan kinerja.

E.g .: ini mencetak baris:

printf '%10000000s\n\x80a' | grep 'a'

tetapi ini tidak:

printf '%10s\n\x80a' | grep 'a'

Ukuran buffer aktual tergantung pada bagaimana file dibaca. Misalnya. membandingkan:

export LC_CTYPE='en_US.UTF-8'
(printf '\n\x80a') | grep 'a'
(printf '\n'; sleep 1; printf '\x80a') | grep 'a'

Dengan sleep, baris pertama diteruskan ke grep walaupun panjangnya hanya 1 byte karena prosesnya tertidur, dan pembacaan kedua tidak memeriksa apakah file tersebut biner.

[~ # ~] rtfs [~ # ~]

git clone git://git.savannah.gnu.org/grep.git 
cd grep
git checkout v2.24

Temukan di mana pesan kesalahan stderr dikodekan:

git grep 'Binary file'

Arahkan kami ke /src/grep.c:

if (!out_quiet && (encoding_error_output
                    || (0 <= nlines_first_null && nlines_first_null < nlines)))
    {
    printf (_("Binary file %s matches\n"), filename);

Jika variabel-variabel tersebut dinamai dengan baik, kami pada dasarnya mencapai kesimpulan.

encoding_error_output

Grepping cepat untuk encoding_error_output Menunjukkan bahwa satu-satunya jalur kode yang dapat memodifikasinya melewati buf_has_encoding_errors:

clen = mbrlen (p, buf + size - p, &mbs);
if ((size_t) -2 <= clen)
  return true;

maka cukup man mbrlen.

nlines_first_null dan nlines

Diinisialisasi sebagai:

intmax_t nlines_first_null = -1;
nlines = 0;

jadi ketika nol ditemukan 0 <= nlines_first_null menjadi benar.

TODO kapan nlines_first_null < nlines Bisa salah? Saya malas.

[~ # ~] posix [~ # ~]

Tidak mendefinisikan opsi biner grep - cari file untuk pola | pubs.opengroup.org , dan GNU grep tidak mendokumentasikannya, jadi RTFS adalah satu-satunya cara .

Salah satu file teks saya tiba-tiba dilihat sebagai biner oleh grep:

$ file foo.txt
foo.txt: ISO-8859 text

Solusi adalah mengonversinya dengan menggunakan iconv:

iconv -t UTF-8 -f ISO-8859-1 foo.txt > foo_new.txt
6
zzapper

Berkas /etc/magic atau /usr/share/misc/magic memiliki daftar urutan yang digunakan perintah file untuk menentukan jenis file.

Catatan biner itu mungkin hanya solusi fallback. Terkadang file dengan pengodean aneh juga dianggap biner.

grep di Linux memiliki beberapa opsi untuk menangani file biner seperti --binary-files atau -U / --binary

5
klapaucius

Sebenarnya menjawab pertanyaan "Apa yang membuat grep menganggap file sebagai biner?", Anda dapat menggunakan iconv:

$ iconv < myfile.Java
iconv: (stdin):267:70: cannot convert

Dalam kasus saya ada karakter Spanyol yang muncul dengan benar di editor teks tetapi grep menganggapnya sebagai biner; iconv output mengarahkan saya ke nomor baris dan kolom karakter tersebut

Dalam kasus NUL karakter, iconv akan menganggapnya normal dan tidak akan mencetak output semacam itu sehingga metode ini tidak cocok

2
golimar

Salah satu siswa saya memiliki masalah ini. Ada bug di grep di Cygwin. Jika file tersebut memiliki karakter non-Ascii, grep dan egrep melihatnya sebagai biner.

2
Joan Pontius

Saya memiliki masalah yang sama. Saya menggunakan vi -b [filename] untuk melihat karakter yang ditambahkan. Saya menemukan karakter kontrol ^@ dan ^M. Kemudian dalam vi ketik :1,$s/^@//g untuk menghapus ^@ karakter. Ulangi perintah ini untuk ^M.

Peringatan: Untuk mendapatkan karakter kontrol "biru" tekan Ctrl+v kemudian Ctrl+M atau Ctrl+@. Kemudian simpan dan keluar vi.

1
Not Sure