Chaîne correspondante avec un nombre fixe de caractères à l'aide de grep

9

J'essaie de trouver tous les 6mots de lettres en utilisant grep. J'ai actuellement ceci:

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

Cependant, je constate que j'obtiens également des résultats tels que: étuis, étude.

Je soupçonne que cela a quelque chose à voir avec les symboles au e-dessus des mots ci-dessus.

Puis-je faire quelque chose pour éviter que cela ne se produise?

Merci de votre aide!


la source

Réponses:

4

grepL'idée d'un caractère dépend des paramètres régionaux . Si vous êtes dans un environnement local non Unicode et que vous récupérez à partir d'un fichier contenant des caractères Unicode, le nombre de caractères ne correspondra pas. Si vous voyez echo $LANGalors les paramètres régionaux dans lesquels vous vous trouvez.

Si vous définissez les variables d'environnement LC_CTYPEet / ou LANGune valeur se terminant par ".UTF-8", vous obtiendrez le bon comportement:

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

Vous pouvez modifier vos paramètres régionaux pour une seule commande en affectant la variable sur la même ligne que la commande.

Avec cette configuration, les caractères multi-octets sont considérés comme des caractères uniques. Si vous souhaitez exclure entièrement les caractères non ASCII, certaines des autres réponses ont des solutions pour vous.


Notez qu'il est toujours possible que les choses se cassent, ou du moins ne fassent pas exactement ce que vous attendez, en présence de combinaisons de personnages . Vous greppouvez traiter la LETTRE MINUSCULE LATINE E + COMBINANT LE CARACTÈRE AIGU CI-DESSUS différemment de la LETTRE MINUSCULE LATINE E AIGU.

Michael Homer
la source
si vous utilisez ., quelque chose comme wăsd'sva correspondre
cuonglm
'est un caractère qui peut raisonnablement faire partie d'une "chaîne avec un nombre fixe de caractères".
Michael Homer
Peut être. Et vous devez définir les deux LC_CTYPEet LANG, quelque chose comme LC_CTYPE=en_US.UTF-8 LANG=en_USsera échoué. Utilisez LC_ALLpour la sécurité.
cuonglm
2

Essaye ça:

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

-xutiliser pour correspondre à toute la ligne, et défini par POSIX (voir grep ).

Voir ici pour une bonne explication de ce qui se LC_ALLpasse. Vous pouvez définir LANGou LC_CTYPEutiliser utf-8 pour obtenir le même comportement. L'ordre prenant effet est LC_ALL=> LANG=> LC_CTYPE.

cuonglm
la source
2

Avec GNU greplorsqu'il est construit avec le support PCRE, vous pouvez faire:

grep -Px '\X{6}'

Tandis que .correspond à un caractère, \Xcorrespond à un idéogramme / graphème.

Dans un environnement local 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

Dans ce dernier études, il y a 7 caractères, 8 octets et 6 graphèmes.

Stéphane Chazelas
la source
Il semble que cela ne fonctionne pas: echo épée | grep -Px '\X{6}'ouputépée
cuonglm
@Gnouc, vous devez l'exécuter dans un environnement local UTF-8 (si ceux éci-dessus ont été encodés en UTF-8).
Stéphane Chazelas
Oh, mes erreurs. Cela fonctionne avec UTF-8.
cuonglm
0

Vous pouvez essayer quelque chose comme:

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

ou si les mots peuvent aussi contenir des nombres, alors:

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

Ajoutez simplement les caractères aux crochets que vous souhaitez en plus de ceux-ci.

Warwick
la source
Cela ne correspondra pas du étudetout, car le caractère ASCII correspondant à l'accent gâchera l'expression régulière.
Alex