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.