Làm thế nào để grep quyết định rằng một tập tin là nhị phân?


8

Tôi có một tệp văn bản utf-8 lớn mà tôi thường tìm kiếm grep. Gần đây grepđã bắt đầu báo cáo rằng đó là một tập tin nhị phân. Tôi có thể tiếp tục tìm kiếm nó grep -a, nhưng tôi đã tự hỏi sự thay đổi nào đã khiến nó quyết định rằng tập tin bây giờ là nhị phân.

Tôi có một bản sao từ tháng trước khi tệp không còn được phát hiện dưới dạng nhị phân, nhưng nó không thực tế đối với diffchúng vì chúng khác nhau trên> 20.000 dòng.

file xác định tập tin của tôi là

Văn bản tiếng Anh UTF-8 Unicode, với các dòng rất dài

Làm thế nào tôi có thể tìm thấy các ký tự / dòng / vv. trong tập tin của tôi đang kích hoạt sự thay đổi này?


Câu hỏi tương tự, không trùng lặp 19907 bao gồm khả năng của NUL nhưng grep -Pc '[\x00-\x1F]'nói rằng tôi không có NUL hoặc bất kỳ chaarcters kiểm soát ANSI nào khác.


Tôi sẽ thử điều này theo thứ tự sau: 1. Chạy nó với strace / ltrace để kiểm tra xem nguyên nhân đầu vào nào gây ra thông điệp 'nhị phân' 2. Kiểm tra nguồn của grep và đọc nó
ott--

@muru: Tôi đang sử dụng gnu grep, nhưng nếu bạn có câu trả lời cho một số phiên bản khác thì tôi cũng sẽ quan tâm.
Charles

Lạ Tôi có một tập tin mà tôi biết có chứa một nulvà một số Escs. Tôi đã thử grepping cho họ. Tôi có thể tìm thấy escs ( \x1B), nhưng nulkhông bao giờ xuất hiện. Thử nghiệm được đưa ra ở trên cho thấy 1, đối với dòng chứa Escs, nhưng không có gì cho bất kỳ phạm vi nào không chứa \x1B. Tôi sẽ không tin tưởng vào bài kiểm tra đó. grep -zc .Thay vào đó hãy thử (nên nhiều hơn số nuls trong tệp của bạn). (Ngoài ra, bạn có thể sử dụng tốt hơn [[:cntrl:]].)
muru

Ngoài ra, hãy thử: sed -z 's/.*\(....\)$/\1/' foo | od -cđể xem một vài ký tự trước NUL(nếu có), điều này có thể dẫn bạn đến vấn đề.
muru

@muru: Tôi sedkhông có -ztùy chọn : sed: invalid option -- 'z'.
Charles

Câu trả lời:


2

Nó dường như là sự hiện diện của ký tự null trong tệp. (Hiển thị ^ @ thường) Tôi đã nhập nhiều ký tự điều khiển khác nhau vào một tệp văn bản (ví dụ như xóa, ^?, Chẳng hạn) và chỉ có ký tự null khiến grep xem xét nó một nhị phân. Điều này chỉ được thử nghiệm cho grep. Các lệnh less và diff, ví dụ, có thể có các phương thức khác nhau. Các ký tự điều khiển nói chung không xuất hiện ngoại trừ trong nhị phân. Các ngoại lệ là các ký tự khoảng trắng: newline (^ M), tab (^ I), formfeed (^ L), tab dọc (^ K) và return (^ J).

Tuy nhiên, các ký tự nước ngoài, như chữ cái tiếng Ả Rập hoặc tiếng Trung Quốc, không phải là ascii tiêu chuẩn, và có lẽ có thể bị nhầm lẫn với các ký tự điều khiển. Có lẽ đó là lý do tại sao nó chỉ là nhân vật null.

Bạn có thể tự kiểm tra bằng cách đưa các ký tự điều khiển vào một tệp văn bản bằng cách sử dụng trình soạn thảo văn bản vim. Chỉ cần chuyển đến chế độ chèn, nhấn control-v và sau đó là ký tự điều khiển.


2

Một triển khai grep hiện đại điển hình chỉ nên khai báo một tệp "nhị phân" nếu có các byte nul bên trong. Bất cứ điều gì khác nên ổn.

Tôi không thể nói cho việc thực hiện grep mà bạn sử dụng ...


1

Một lỗi mã hóa theo mbrlen () cũng khiến GNU grep 2.24 coi đó là nhị phân

Ví dụ:

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

bởi vì \x80không thể là byte đầu tiên của điểm Unicode UTF-8: https://en.wikipedia.org/wiki/UTF-8#Mô tả

Đây là khả năng duy nhất khác bên cạnh NUL.

grepGiải thích mã nguồn GNU dẫn đến kết luận này: Điều gì khiến grep coi một tệp là nhị phân?

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.