Mencocokkan string dengan jumlah karakter tetap menggunakan grep

9

Saya mencoba menemukan semua 6kata menggunakan huruf grep. Saat ini saya punya ini:

grep "^.\{6\}$" myfile.txt 

Namun, saya menemukan bahwa saya juga mendapatkan hasil seperti: étuis, étude.

Saya menduga itu ada hubungannya dengan simbol edi atas pada kata-kata di atas.

Adakah yang bisa saya lakukan untuk memastikan ini tidak terjadi?

Terima kasih atas bantuan Anda!


sumber

Jawaban:

4

grepGagasan karakter bergantung pada lokal . Jika Anda berada di lokal non-Unicode dan Anda mengambil dari file dengan karakter Unicode di dalamnya maka jumlah karakter tidak akan cocok. Jika Anda echo $LANGmaka Anda akan melihat tempat Anda berada.

Jika Anda mengatur variabel lingkungan LC_CTYPEdan / atau LANGke nilai yang diakhiri dengan ".UTF-8" maka Anda akan mendapatkan perilaku yang benar:

$ cat data
étuis
letter
éééééé
$ LANG=C grep -E '^.{6}$' data
étuis
letter
$ LANG=en_US.UTF_8 grep -E '^.{6}$' data
letter
éééééé
$

Anda dapat mengubah lokal hanya untuk satu perintah dengan menetapkan variabel pada baris yang sama dengan perintah.

Dengan konfigurasi ini, karakter multi-byte dianggap sebagai karakter tunggal. Jika Anda ingin mengecualikan karakter non-ASCII sepenuhnya, beberapa jawaban lain memiliki solusi untuk Anda.


Perhatikan bahwa masih mungkin hal-hal untuk dipecahkan, atau setidaknya tidak melakukan apa yang Anda harapkan, dengan adanya penggabungan karakter . Anda grepdapat memperlakukan SURAT KECIL LATIN E + KARAKTER GABUNGAN AKUT DI ATAS berbeda dari SURAT KECIL LATIN E DENGAN AKUT.

Michael Homer
sumber
jika Anda menggunakan ., sesuatu seperti wăsd'sakan cocok
cuonglm
'adalah karakter yang dapat secara wajar menjadi bagian dari "string dengan jumlah karakter tetap".
Michael Homer
Mungkin. Dan Anda harus mengatur keduanya LC_CTYPEdan LANG, sesuatu seperti LC_CTYPE=en_US.UTF-8 LANG=en_USakan gagal. Gunakan LC_ALLuntuk keamanan.
cuonglm
2

Coba ini:

LC_ALL=C.UTF-8 grep -x '[_[:alnum:]]\{6\}' file

-xgunakan untuk mencocokkan seluruh baris, dan didefinisikan oleh POSIX (Lihat grep ).

Lihat di sini untuk penjelasan yang baik tentang apa yang LC_ALLdilakukan. Anda dapat mengatur LANGatau LC_CTYPEmenggunakan utf-8 untuk mendapatkan perilaku yang sama. Pengaruh pengambilan pesanan adalah LC_ALL=> LANG=> LC_CTYPE.

cuonglm
sumber
2

Dengan GNU grepsaat dibangun dengan dukungan PCRE, Anda dapat melakukan:

grep -Px '\X{6}'

Sementara .cocok dengan karakter, \Xcocok dengan ideogram / graphem.

Di lokal UTF-8:

$ locale charmap
UTF-8
$ printf '\u00e9tuis\n\u00e9tudes\n' | grep -Px '\X{6}'
études
$ printf 'e\u0301tuis\ne\u0301tudes\n' | grep -Px '\X{6}'
études

Dalam yang terakhir études, ada 7 karakter, 8 byte, dan 6 graphem.

Stéphane Chazelas
sumber
Tampaknya tidak berfungsi: echo épée | grep -Px '\X{6}'ouputépée
cuonglm
@ Gnouc, Anda perlu menjalankannya di lokal UTF-8 (jika yang di éatas disandikan dalam UTF-8).
Stéphane Chazelas
Oh, kesalahanku. Ini bekerja dengan UTF-8.
cuonglm
0

Anda dapat mencoba sesuatu seperti:

grep "^[A-Za-z]\{6\}$" myfile.txt

atau jika kata-kata itu mungkin mengandung angka juga, maka:

grep "^[A-Za-z0-9]\{6\}$" myfile.txt

Cukup tambahkan karakter apa saja ke dalam tanda kurung siku yang Anda inginkan sebagai tambahan.

Warwick
sumber
Ini tidak akan cocok étudesama sekali, karena karakter ASCII yang sesuai dengan aksen akan mengacaukan regex.
Alex