grep
adalah alat yang salah untuk pekerjaan itu.
Anda melihat � U+FFFD REPLACEMENT CHARACTER
bukan karena itu benar-benar dalam konten file, tetapi karena Anda melihat file biner dengan alat yang seharusnya hanya menangani input berbasis teks. Cara standar untuk menangani input yang tidak valid (yaitu, data biner acak) adalah dengan mengganti semua yang tidak valid di lokal saat ini (kemungkinan besar UTF-8) dengan U+FFFD sebelum menyentuh layar.
Itu berarti sangat mungkin bahwa \xEF\xBF\xBD
literal (urutan byte UTF-8 untuk karakter U+FFFD) tidak pernah muncul di file. grep
sepenuhnya benar dalam memberi tahu Anda, tidak ada.
Salah satu cara untuk mendeteksi apakah suatu file berisi beberapa biner yang tidak diketahui adalah dengan file(1)
perintah:
$ head -c 100 /dev/urandom > rubbish.bin
$ file rubbish.bin
rubbish.bin: data
Untuk jenis file yang tidak diketahui, hanya akan tertulis data
. Coba
$ file out.txt | grep '^out.txt: data$'
untuk memeriksa apakah file tersebut benar-benar berisi sembarang biner dan kemungkinan besar sampah.
Jika Anda ingin memastikan bahwa out.txt
adalah file teks berenkode UTF-8 saja, sebagai alternatif, Anda dapat menggunakan iconv
:
$ iconv -f utf-8 -t utf-16 out.txt >/dev/null
TL;DR:
grep -axv '.*' out.txt
jawaban panjang
Kedua jawaban yang ada sangat menyesatkan dan pada dasarnya salah.
Untuk menguji, Dapatkan dua file ini (dari pengembang yang sangat terkenal:Markus Kuhn ):
$ wget https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-demo.txt
$ wget https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
Demo
UTF-8-demo.txt
pertama adalah file yang dirancang untuk menunjukkan seberapa baik UTF-8 mampu menampilkan banyak bahasa, matematika, braille, dan banyak jenis karakter berguna lainnya. Lihatlah dengan editor teks (yang mengerti utf-8) dan Anda akan melihat banyak contoh dan tidak �
.
Tes yang diajukan oleh satu jawaban:untuk membatasi rentang karakter ke \x00-\x7F
akan menolak hampir semua yang ada di dalam file ini.
Itu sangat salah dan tidak akan menghapus �
karena tidak ada di file itu .
Menggunakan tes yang direkomendasikan dalam jawaban itu akan menghapus 72.5 %
dari file:
$ grep -oP "[^\x00-\x7F]" UTF-8-demo.txt | tr -d '\n' | wc -c
10192
$ cat UTF-8-demo.txt | wc -c
14058
Itu (untuk sebagian besar tujuan praktis) seluruh file. File yang dirancang dengan sangat baik untuk menampilkan karakter yang benar-benar valid.
Uji
File kedua dirancang untuk mencoba beberapa kasus perbatasan untuk mengonfirmasi bahwa pembaca utf-8 melakukan pekerjaan dengan baik. Ini berisi di dalam banyak karakter yang akan menyebabkan '�' ditampilkan. Tapi rekomendasi jawaban lain (yang terpilih) menggunakan file
gagal total dengan file ini. Hanya menghapus nol byte (\0
) (yang secara teknis adalah ASCII yang valid) dan \x7f
byte (DEL - hapus) (yang jelas merupakan karakter ASCII juga) akan membuat semua file yang valid untuk file
perintah:
$ cat UTF-8-test.txt | tr -d '\0\177' > a.txt
$ file a.txt
a.txt: Non-ISO extended-ASCII text, with LF, NEL line terminators
Tidak hanya file
gagal mendeteksi banyak karakter yang salah, tetapi juga gagal mendeteksi dan melaporkan bahwa itu adalah file berenkode UTF-8.
Dan ya, file
dapat mendeteksi dan melaporkan teks berenkode UTF-8:
$ echo "ééakjfhhjhfakjfhfhaéá" | file -
/dev/stdin: UTF-8 Unicode text
Juga, file
gagal melaporkan sebagai ASCII sebagian besar karakter kontrol dalam rentang 1 hingga 31. Ini (file
) melaporkan beberapa rentang sebagai data
:
$ printf '%b' "$(printf '\\U%x' {1..6})" | file -
/dev/stdin: data
Lainnya sebagai ASCII text
:
$ printf '%b' "$(printf '\\U%x' 7 {9..12})" | file -
/dev/stdin: ASCII text
Sebagai rentang karakter yang dapat dicetak (dengan baris baru):
$ printf '%b' "$(printf '\\U%x' {32..126} 10)" | file -
/dev/stdin: ASCII text
Tetapi beberapa rentang dapat menyebabkan hasil yang aneh:
$ printf '%b' "$(printf '\\U%x' {14..26})" | file -
/dev/stdin: Atari MSA archive data, 4113 sectors per track, starting track: 5141, ending track: 5655
Program file
bukan alat untuk mendeteksi teks, tetapi untuk mendeteksi sihir angka dalam program atau file yang dapat dijalankan.
Rentang file
deteksi, dan jenis terkait yang dilaporkan yang saya temukan adalah:
-
Nilai satu byte, kebanyakan ascii:
{1..6} {14..26} {28..31} 127 :data {128..132} {134..159} :Non-ISO extended-ASCII text 133 :ASCII text, with LF, NEL line terminators 27 :ASCII text, with escape sequences 13 :ASCII text, with CR, LF line terminators 8 :ASCII text, with overstriking 7 {9..12} {32..126} :ASCII text {160..255} :ISO-8859 text
-
Rentang berenkode Utf-8:
{1..6} {14..26} {28..31} 127 :data 27 :ASCII text, with escape sequences 13 :ASCII text, with CR, LF line terminators 8 :ASCII text, with overstriking 7 {9..12} {32..126} :ASCII text {128..132} {134..159} :UTF-8 Unicode text 133 :UTF-8 Unicode text, with LF, NEL line terminators {160..255} :UTF-8 Unicode text {256..5120} :UTF-8 Unicode text
Salah satu solusi yang mungkin ada di bawah.
Jawaban Sebelumnya.
Nilai Unicode untuk karakter yang Anda posting adalah:
$ printf '%x\n' "'�"
fffd
Ya, itu adalah Karakter Unicode 'KARAKTER PENGGANTI' (U+FFFD). Itu adalah karakter yang digunakan untuk mengganti tidak valid Karakter Unicode ditemukan dalam teks. Ini adalah "bantuan visual", bukan karakter nyata. Untuk menemukan dan mencantumkan setiap baris lengkap yang berisi UNICODE yang tidak valid penggunaan karakter:
grep -axv '.*' out.txt
tetapi jika Anda hanya ingin mendeteksi jika ada karakter yang tidak valid, gunakan:
grep -qaxv '.*' out.txt; echo $?
Jika hasilnya adalah 1
file bersih, jika tidak akan menjadi nol 0
.
Jika yang Anda tanyakan adalah:bagaimana menemukan �
karakter, kemudian, gunakan ini:
➤ a='Basically, if the file "out.txt" contains "�" anywhere in the file I'
➤ echo "$a" | grep -oP $(printf %b \\Ufffd)
�
Atau jika sistem Anda memproses teks UTF-8 dengan benar, cukup:
➤ echo "$a" | grep -oP '�'
�
Jawaban paling awal ini untuk postingan asli yaitu:
Cara grep untuk unicode � dalam skrip bash
if grep -q "�" out.txt then echo "working" else cat out.txt fi
Pada dasarnya, jika file "out.txt" berisi "�" di mana pun di file, saya ingin gema "berfungsi" DAN jika file "out.txt" TIDAK berisi "�" di mana pun di file, maka saya akan menyukainya untuk cat out.txt
Coba
grep -oP "[^\x00-\x7F]"
dengan if .. then
pernyataan sebagai berikut:
if grep -oP "[^\x00-\x7F]" file.txt; then
echo "grep found something ..."
else
echo "Nothing found!"
fi
Penjelasan:
-P
,--perl-regexp
:PATTERN adalah ekspresi reguler Perl-o
,--only-matching
:hanya menampilkan bagian dari POLA pencocokan garis[^\x00-\x7F]
adalah regex untuk mencocokkan satu karakter non-ASCII.[[:ascii:]]
- cocok dengan satu karakter ASCII[^[:ascii:]]
- cocok dengan satu karakter non-ASCII
di bash
LC_COLLATE=C grep -o '[^ -~]' file