Stringa corrispondente con un numero fisso di caratteri usando grep


9

Sto cercando di trovare tutte le 6parole in lettere usando grep. Al momento ho questo:

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

Tuttavia, sto scoprendo che sto ottenendo anche risultati come: étuis, étude.

Ho il sospetto che abbia qualcosa a che fare con i simboli sopra le eparole sopra.

C'è qualcosa che posso fare per garantire che ciò non accada?

Grazie per l'aiuto!

Risposte:


4

grepL 'idea di un personaggio dipende dalle impostazioni locali . Se ci si trova in una locale non Unicode e si esegue il grep da un file contenente caratteri Unicode, il conteggio dei caratteri non corrisponderà. Se echo $LANGpoi vedrai le impostazioni internazionali in cui ti trovi.

Se imposti le variabili LC_CTYPEe / o LANGambiente su un valore che termina con ".UTF-8", otterrai il comportamento giusto:

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

È possibile modificare le impostazioni internazionali per un solo comando assegnando la variabile sulla stessa riga del comando.

Con questa configurazione, i caratteri multibyte sono considerati come singoli caratteri. Se vuoi escludere del tutto i caratteri non ASCII, alcune delle altre risposte hanno delle soluzioni per te.


Nota che è ancora possibile che le cose si rompano, o almeno non facciano esattamente quello che ti aspetti, in presenza della combinazione di personaggi . Il tuo greppuò trattare latino: lettera E + COMBINAZIONE DI CARATTERE ACUTA SOPRA diverso rispetto latino: lettera E con accento acuto.


se usi ., qualcosa di simile wăsd'scorrisponderà
cuonglm

'è un carattere che può ragionevolmente far parte di una "stringa con un numero fisso di caratteri".
Michael Homer,

Può essere. E dovresti impostare entrambi LC_CTYPEe LANG, qualcosa del genere LC_CTYPE=en_US.UTF-8 LANG=en_USfallirà. Utilizzare LC_ALLper la sicurezza.
cuonglm

2

Prova questo:

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

-xusare per abbinare l'intera linea e definito da POSIX (Vedi grep ).

Vedi qui per una buona spiegazione di cosa LC_ALLfa. È possibile impostare LANGo LC_CTYPEutilizzare utf-8 per ottenere lo stesso comportamento. L'ordine che ha effetto è LC_ALL=> LANG=> LC_CTYPE.


2

Con GNU grepquando creato con il supporto PCRE, puoi fare:

grep -Px '\X{6}'

Mentre .corrisponde a un personaggio, \Xcorrisponde a un ideogramma / graphem.

In una locale 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

In quest'ultimo caso études, ci sono 7 caratteri, 8 byte e 6 grafici.


Sembra non funzionare: echo épée | grep -Px '\X{6}'ouputépée
cuonglm

@Gnouc, devi eseguirlo in una locale UTF-8 (se quelli ésopra erano codificati in UTF-8).
Stéphane Chazelas,

Oh, i miei errori Funziona con UTF-8.
cuonglm

0

Potresti provare qualcosa del tipo:

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

o se le parole possono contenere anche numeri, allora:

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

Aggiungi solo i caratteri alle parentesi quadre che desideri oltre a questi.


Questo non corrisponderà étudeaffatto, perché il carattere ASCII corrispondente all'accento creerà confusione nella regex.
Alex,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.