Cadena coincidente con un número fijo de caracteres usando grep

9

Estoy tratando de encontrar todas las 6palabras de letras usando grep. Actualmente tengo esto:

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

Sin embargo, estoy descubriendo que también estoy obteniendo resultados como: étuis, étude.

Sospecho que tiene algo que ver con los símbolos de arriba een las palabras de arriba.

¿Hay algo que pueda hacer para garantizar que esto no suceda?

¡Gracias por tu ayuda!


fuente

Respuestas:

4

grepLa idea de un personaje depende de la localidad . Si está en una configuración regional que no es Unicode y selecciona un archivo con caracteres Unicode, entonces el recuento de caracteres no coincidirá. Si lo echo $LANGhaces, verás la ubicación en la que te encuentras.

Si establece las LC_CTYPEy / o LANGvariables de entorno a un valor que termina con" .UTF-8" por lo que recibirá el comportamiento correcto:

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

Puede cambiar su configuración regional para un solo comando asignando la variable en la misma línea que el comando.

Con esta configuración, los caracteres de varios bytes se consideran caracteres únicos. Si desea excluir por completo los caracteres que no son ASCII, algunas de las otras respuestas tienen soluciones para usted.


Tenga en cuenta que todavía es posible que las cosas se rompan, o al menos no hagan exactamente lo que espera, en presencia de caracteres combinados . Su greppuede tratar Letra latina minúscula E + COMBINACIÓN DE CARACTER AGUDO POR ENCIMA diferente que E Letra latina minúscula con acento agudo.

Michael Homer
fuente
si lo usas ., algo así wăsd'scoincidirá
cuonglm
'es un carácter que razonablemente puede ser parte de una "cadena con un número fijo de caracteres".
Michael Homer
Tal vez. Y debe configurar ambos LC_CTYPEy LANG, algo así LC_CTYPE=en_US.UTF-8 LANG=en_USserá fallido. Uso LC_ALLpor seguridad.
Cuonglm
2

Prueba esto:

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

-xse usa para hacer coincidir la línea completa y se define por POSIX (Ver grep )

Vea aquí para una buena explicación de lo que LC_ALLhace. Puede configurar LANGo LC_CTYPEusar utf-8 para obtener el mismo comportamiento. El orden que toma efecto es LC_ALL=> LANG=> LC_CTYPE.

Cuonglm
fuente
2

Con GNU grepcuando se construye con soporte PCRE, puede hacer:

grep -Px '\X{6}'

Mientras .coincide con un personaje, \Xcoincide con un ideograma / gráfico.

En un entorno 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

En ese último études, hay 7 caracteres, 8 bytes y 6 grafemas.

Stéphane Chazelas
fuente
Parece no funciona: echo épée | grep -Px '\X{6}'ouputépée
cuonglm
@Gnouc, debe ejecutar eso en un entorno local UTF-8 (si los éanteriores se codificaron en UTF-8).
Stéphane Chazelas
Oh, mis errores Funciona con UTF-8.
Cuonglm
0

Podrías probar algo como:

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

o si las palabras también pueden contener números, entonces:

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

Simplemente agregue cualquier carácter a los corchetes que desee además de estos.

Warwick
fuente
Esto no coincidirá étudeen absoluto, porque el carácter ASCII correspondiente al acento desordenará la expresión regular.
Alex