Saya memiliki beberapa file XML yang sangat besar dan saya mencoba menemukan garis yang berisi karakter non-ASCII. Saya sudah mencoba yang berikut ini:
grep -e "[\x{00FF}-\x{FFFF}]" file.xml
Tapi ini mengembalikan setiap baris dalam file, terlepas dari apakah baris tersebut mengandung karakter dalam rentang yang ditentukan.
Apakah saya salah sintaks atau saya melakukan sesuatu yang salah? Saya juga sudah mencoba:
egrep "[\x{00FF}-\x{FFFF}]" file.xml
(dengan tanda kutip tunggal dan ganda di sekitar pola).
Jawaban:
Anda dapat menggunakan perintah:
Ini akan memberi Anda nomor baris, dan akan menyoroti karakter non-ascii berwarna merah.
Dalam beberapa sistem, tergantung pada pengaturan Anda, hal di atas tidak akan berfungsi, sehingga Anda dapat memahami invers
Perhatikan juga, bahwa bit penting adalah
-P
flag yang sama dengan--perl-regexp
: sehingga akan menginterpretasikan pola Anda sebagai ekspresi reguler Perl. Itu juga mengatakan itusumber
grep
(pada OS X 10.8 Mountain Lion), karena tidak mendukungP
opsi.grep
tersedia didupes
perpustakaan Homebrew (aktifkan menggunakanbrew tap homebrew/dupes
):brew install grep
dupes
pustaka adalah menginstalpcre
:brew install pcre
... sebagai bagian dari ini, Anda akan mendapatkanpcregrep
utilitas, yang dapat Anda gunakan sebagai berikut:pcregrep --color='auto' -n "[\x80-\xFF]" file.xml
brew
pengguna Mac , coreutils GNU dapat diinstal denganbrew install coreutils
. Ini akan memberi Anda banyak alat GNU yang diawali dengan 'g' - dalam hal ini digunakanggrep
. Ini harus menghindari masalah yang timbul dari penggantian utilitas sistem, karena skrip Mac khusus sistem sekarang bergantung pada BSD grep.ag "[\x80-\xFF]" file
Anda hanya perlu menginstalthe_silver_searcher
Daripada membuat asumsi tentang rentang byte karakter non-ASCII, seperti kebanyakan solusi di atas lakukan, itu IMO sedikit lebih baik untuk secara eksplisit tentang kisaran byte sebenarnya dari karakter ASCII sebagai gantinya.
Jadi solusi pertama misalnya akan menjadi:
(yang pada dasarnya memahami karakter apa pun di luar rentang ASCII heksadesimal: dari \ x00 hingga \ x7F)
Pada Mountain Lion yang tidak berfungsi (karena kurangnya dukungan PCRE dalam BSD grep) , tetapi dengan
pcre
diinstal melalui Homebrew, yang berikut ini akan berfungsi juga:Adakah pro atau kontra yang bisa dipikirkan orang?
sumber
LC_COLLATE=C grep $'[^\1-\177]'
berfungsi (untuk file tanpa byte nol)Berikut ini berfungsi untuk saya:
Karakter non-ASCII mulai dari 0x80 dan pergi ke 0xFF ketika melihat byte. Grep (dan keluarga) tidak melakukan pemrosesan Unicode untuk menggabungkan karakter multi-byte menjadi satu entitas untuk pencocokan regex seperti yang Anda inginkan. The
-P
pilihan dalam grep saya memungkinkan penggunaan\xdd
lolos di kelas karakter untuk mencapai apa yang Anda inginkan.sumber
echo '소녀시대' | grep -P "[\x80-\xFF]"
tidak mengembalikan apa pun untuk saya - dapatkah orang lain mengkonfirmasi? (GNU grep 2.21)echo '소녀시대' | grep -P "[^\x00-\x7F]"
. Atau cukup gunakanthe_silver_searcher
seperti yang ditunjukkan oleh @slf:echo '소녀시대' | ag "[\x80-\xFF]"
Dalam perl
sumber
perl -lne 'print if /[^[:ascii:]]/' file.xml
Cara mudah adalah mendefinisikan karakter non-ASCII ... sebagai karakter yang bukan karakter ASCII.
Tambahkan tab setelah itu
^
jika perlu.Pengaturan
LC_COLLATE=C
menghindari kejutan yang tidak menyenangkan tentang arti rentang karakter di banyak tempat. PengaturanLC_CTYPE=C
diperlukan untuk mencocokkan karakter byte tunggal - jika tidak, perintah akan melewatkan urutan byte yang tidak valid dalam pengkodean saat ini. PengaturanLC_ALL=C
menghindari efek yang bergantung pada lokal sama sekali.sumber
echo "A" | LC_COLLATE=C grep '[^ -~]'
mengembalikan pertandinganLC_ALL=en_US.UTF-8
, itu mengalahkanLC_COLLATE
pengaturan. Anda seharusnya tidak memiliki ini di lingkungan Anda!LC_ALL
hanya untuk memaksa tugas tertentu untuk menggunakan lokal tertentu, biasanyaC
. Untuk mengatur lokal default untuk semua kategori, aturLANG
.LC_ALL=C
, berperilaku berbeda di Mac OS X dan Ubuntu. Setelah saya menambahkan pengaturan ini, mereka memberikan hasil yang sama.Berikut adalah varian lain yang saya temukan yang menghasilkan hasil yang sama sekali berbeda dari pencarian grep
[\x80-\xFF]
dalam jawaban yang diterima. Mungkin akan berguna bagi seseorang untuk menemukan karakter non-ascii tambahan:grep --color='auto' -P -n "[^[:ascii:]]" myfile.txt
Catatan: grep (a Mac) komputer saya tidak memiliki
-P
opsi, jadi saya lakukanbrew install grep
dan memulai panggilan di atas denganggrep
alih - alihgrep
.sumber
Kode berikut berfungsi:
Ganti
/tmp
dengan nama direktori yang ingin Anda cari.sumber
Mencari karakter yang tidak dapat dicetak. TLDR; Ringkasan bisnis plan
LC_ALL=C
diperlukan untuk membuat grep melakukan apa yang Anda harapkan dengan unicode diperpanjangSO pencari non-ascii char yang disukai:
seperti pada jawaban teratas, grep terbalik:
seperti pada jawaban teratas tetapi DENGAN
LC_ALL=C
:. . lebih lanjut. . detail yang luar biasa tentang ini:. . .
Saya setuju dengan Harvey yang terkubur dalam komentar, seringkali lebih berguna untuk mencari karakter yang tidak dapat dicetak ATAU mudah untuk berpikir non-ASCII ketika Anda benar-benar harus berpikir tidak dapat dicetak. Harvey menyarankan "gunakan ini:"
[^\n -~]
". Tambahkan \ r untuk file teks DOS. Itu berarti"[^\x0A\x020-\x07E]
"dan tambahkan \ x0D untuk CR"Juga, menambahkan -c (tunjukkan jumlah pola yang cocok) ke grep berguna saat mencari karakter yang tidak dapat dicetak karena string yang cocok dapat mengacaukan terminal.
Saya menemukan menambahkan rentang 0-8 dan 0x0e-0x1f (ke kisaran 0x80-0xff) adalah pola yang berguna. Ini tidak termasuk TAB, CR dan LF dan satu atau dua karakter yang tidak biasa dicetak. Jadi IMHO pola grep yang cukup berguna (meskipun kasar) adalah yang INI:
SEBENARNYA, secara umum Anda perlu melakukan ini:
kerusakan:
Contoh praktis penggunaan find untuk menangkap semua file di bawah direktori saat ini:
Anda mungkin ingin sesekali menyesuaikan grep. misalnya karakter BS (0x08 - backspace) yang digunakan dalam beberapa file yang dapat dicetak atau untuk mengecualikan VT (0x0B - tab vertikal). Karakter BEL (0x07) dan ESC (0x1B) juga dapat dianggap dapat dicetak dalam beberapa kasus.
UPDATE: Saya harus meninjau kembali ini baru-baru ini. Dan, YYMV tergantung pada pengaturan terminal / ramalan cuaca matahari NAMUN. . Saya perhatikan bahwa grep tidak menemukan banyak karakter unicode atau extended. Meskipun secara intuitif mereka harus cocok dengan kisaran 0x80 hingga 0xff, 3 dan 4 byte karakter unicode tidak cocok. ??? Adakah yang bisa menjelaskan ini? IYA. @frabjous bertanya dan @calandoa menjelaskan itu
LC_ALL=C
harus digunakan untuk mengatur lokal untuk perintah untuk membuat grep cocok.mis. lokal saya
LC_ALL=
kosonggrep dengan
LC_ALL=
kecocokan kosong 2 byte karakter yang dikodekan tetapi tidak 3 dan 4 byte yang dikodekan:grep with
LC_ALL=C
tampaknya cocok dengan semua karakter diperluas yang Anda inginkan:Kecocokan perl INI (sebagian ditemukan di tempat lain di stackoverflow) ATAU grep terbalik pada jawaban atas DO tampaknya menemukan SEMUA karakter ~ aneh ~ dan ~ luar biasa ~ "non-ascii" tanpa menetapkan lokal:
SO pencari non-ascii char yang disukai:
seperti pada jawaban teratas, grep terbalik:
seperti pada jawaban teratas tetapi DENGAN
LC_ALL=C
:sumber
Anehnya, saya harus melakukan ini hari ini! Saya akhirnya menggunakan Perl karena saya tidak bisa membuat grep / egrep bekerja (bahkan dalam mode -P). Sesuatu seperti:
Untuk karakter unicode (seperti
\u2212
dalam contoh di bawah) gunakan ini:sumber
Mungkin menarik untuk mengetahui cara mencari satu karakter unicode. Perintah ini dapat membantu. Anda hanya perlu tahu kode di UTF8
sumber
Menemukan semua karakter non-ascii memberi kesan bahwa seseorang sedang mencari string unicode atau bermaksud untuk menghapus karakter tersebut secara individual.
Untuk yang pertama, coba salah satu dari ini (variabel
file
digunakan untuk otomatisasi):Vanilla grep tidak berfungsi dengan benar tanpa LC_ALL = C seperti yang tercantum dalam jawaban sebelumnya.
Kisaran ASCII adalah
x00-x7F
, ruangx20
, karena string memiliki spasi, rentang negatif menghilangkannya.Kisaran Non-ASCII adalah
x80-xFF
, karena string memiliki spasi, rentang positif menambahkannya.String dianggap setidaknya 7 karakter berturut-turut dalam rentang tersebut.
{7,}
.Untuk keluaran yang dapat dibaca shell,
uchardet $file
mengembalikan tebakan pengkodean file yang diteruskan ke iconv untuk interpolasi otomatis.sumber
uchardet
perintah. Terima kasih untuk itu!