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 NUL
karakter ascii , yang saya percaya adalah artefak dari dump database.
Jadi apa yang membuat grep menganggap file-file ini sebagai biner? The NUL
karakter? Apakah ada tanda pada filesystem? Apa yang harus saya ubah untuk mendapatkan grep untuk menunjukkan kepada saya baris yang cocok?
--null-data
semoga bermanfaat jikaNUL
pembatas.Jawaban:
Jika ada
NUL
karakter di mana saja di dalam file, grep akan menganggapnya sebagai file biner.Mungkin ada solusi seperti ini
cat file | tr -d '\000' | yourgrep
untuk menghilangkan semua null terlebih dahulu, lalu mencari melalui file.sumber
-a
/--text
, setidaknya dengan GNU grep.NUL
(mungkin karena itu memanggil printf C dan memberikannya baris yang cocok?). Pada sistem seperti itu,grep cmd .sh_history
akan kembali sebanyak baris kosong karena ada baris yang cocok dengan 'cmd', karena setiap baris sh_history memiliki format tertentu denganNUL
pada awal setiap baris. (tapi komentar Anda "setidaknya pada GNU grep" mungkin menjadi kenyataan. Saya tidak punya satu untuk menguji sekarang, tapi saya berharap mereka menangani ini dengan baik)grep
pada cygwin dianggap biner karena memiliki tanda hubung panjang (0x96) dan bukan tanda hubung ASCII / minus (0x2d) biasa. Saya kira jawaban ini menyelesaikan masalah OP, tetapi tampaknya tidak lengkap.grep -a
bekerja untuk saya:sumber
Anda dapat menggunakan
strings
utilitas untuk mengekstrak konten teks dari file apapun dan kemudian pipa melaluigrep
, seperti ini:strings file | grep pattern
.sumber
GNU grep 2.24 RTFS
Kesimpulan: 2 dan 2 hanya kasus:
NUL
misalnyaprintf 'a\0' | grep 'a'
kesalahan penyandian menurut C99
mbrlen()
, mis:karena
\x80
tidak bisa menjadi byte pertama dari titik Unicode UTF-8 : UTF-8 - Keterangan | en.wikipedia.orgSelanjutnya, seperti yang disebutkan oleh Stéphane Chazelas Apa yang membuat grep menganggap file sebagai biner? | Unix & Linux Stack Exchange , pemeriksaan tersebut hanya dilakukan hingga membaca buffer pertama dengan panjang TODO.
Hanya sampai buffer pertama dibaca
Jadi, jika NUL atau kesalahan pengodean terjadi di tengah file yang sangat besar, itu mungkin akan diterima.
Saya membayangkan ini untuk alasan kinerja.
Misalnya: ini mencetak baris:
tetapi ini tidak:
Ukuran buffer aktual tergantung pada bagaimana file dibaca. Misalnya bandingkan:
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
Temukan di mana pesan kesalahan stderr dikodekan:
Arahkan kami ke
/src/grep.c
: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 melewatibuf_has_encoding_errors
:lalu saja
man mbrlen
.nlines_first_null dan nlines
Diinisialisasi sebagai:
jadi ketika null ditemukan
0 <= nlines_first_null
menjadi true.TODO kapan bisa
nlines_first_null < nlines
salah? Saya malas.POSIX
Tidak mendefinisikan opsi biner grep - cari file untuk suatu pola | pubs.opengroup.org , dan GNU grep tidak mendokumentasikannya, jadi RTFS adalah satu-satunya cara.
sumber
(printf '\n\0y') | grep y
dengan(printf '\n'; sleep 1; printf '\0y') | grep y
misalnya.export LC_CTYPE='en_US.UTF-8'
seperti pada contoh saya, atau yang lain? Tapi baca: contoh luar biasa, ditambahkan ke jawaban. Anda jelas telah membaca sumbernya lebih dari saya, mengingatkan saya pada koan peretas itu "Siswa tercerahkan" :-)Salah satu file teks saya tiba-tiba dilihat sebagai biner oleh grep:
Solusi adalah mengonversinya dengan menggunakan
iconv
:sumber
0xFC
heksadesimal, jadi di luar kisaran grep akan mengharapkan utf8 (hingga0x7F
). Periksa dengan printf 'a \ x7F' | | grep 'a' seperti yang dijelaskan Ciro di atas.File
/etc/magic
atau/usr/share/misc/magic
memiliki daftar urutan yangfile
digunakan perintah untuk menentukan jenis file.Perhatikan bahwa biner mungkin hanya solusi mundur. Terkadang file dengan pengodean aneh juga dianggap biner.
grep
Linux memiliki beberapa opsi untuk menangani file biner seperti--binary-files
atau-U / --binary
sumber
mbrlen()
. Contoh dan sumber interpretasi di: unix.stackexchange.com/a/276028/32558Salah satu siswa saya memiliki masalah ini. Ada bug di
grep
dalamCygwin
. Jika file tersebut memiliki karakter non-Ascii,grep
danegrep
melihatnya sebagai biner.sumber
Sebenarnya menjawab pertanyaan "Apa yang membuat grep menganggap file sebagai biner?", Anda dapat menggunakan
iconv
:Dalam kasus saya ada karakter Spanyol yang muncul dengan benar di editor teks tetapi grep menganggapnya sebagai biner;
iconv
output menunjuk saya ke nomor baris dan kolom karakter tersebutDalam hal
NUL
karakter,iconv
akan menganggapnya normal dan tidak akan mencetak output semacam itu sehingga metode ini tidak cocoksumber
Saya memiliki masalah yang sama. Saya dulu
vi -b [filename]
melihat karakter yang ditambahkan. Saya menemukan karakter kontrol^@
dan^M
. Kemudian ketik vi:1,$s/^@//g
untuk menghapus^@
karakter. Ulangi perintah ini untuk^M
.Peringatan: Untuk mendapatkan karakter kontrol "biru" tekan Ctrl+ vlalu Ctrl+ Matau Ctrl+ @. Kemudian simpan dan keluar vi.
sumber