Estoy tratando de escribir una expresión regular que muestre todas las palabras que tengan 10 caracteres de longitud, y ninguna de las letras se repita.
Hasta ahora, tengo
grep --colour -Eow '(\w{10})'
Cuál es la primera parte de la pregunta. ¿Cómo haría para verificar la "singularidad"? Realmente no tengo ni idea, aparte de eso necesito usar referencias anteriores.
grep
regular-expression
Dylan Meeus
fuente
fuente
Respuestas:
excluye palabras que tienen dos caracteres idénticos.
excluye los que tienen caracteres repetidos.
POSIXY:
tr
coloca las palabras en su propia línea al convertir cualquier ssecuencia de caracteres que no sean palabras ( ccomplemento de alfanumérico y guión bajo) en un carácter de nueva línea.O con uno
grep
:(excluya líneas de menos de 10 y más de 10 caracteres y aquellas con un carácter que aparezca al menos dos veces).
Con uno
grep
solo (GNU grep con soporte PCRE opcregrep
):Es decir, un límite de palabra (
\b
) seguido de una secuencia de 10 caracteres de palabra (siempre que cada uno no sea seguido por una secuencia de caracteres de palabra y ellos mismos, utilizando el operador PCRE de vista previa negativo(?!...)
).Tenemos suerte de que funcione aquí, ya que no muchos motores regexp funcionan con referencias inversas dentro de las partes repetidas.
Tenga en cuenta que (con mi versión de GNU grep al menos)
No funciona pero
does (as
echo aa | grep -Pw '(.)\2'
) que suena como un error.Es posible que desee:
si desea
\w
o\b
considerar cualquier letra como un componente de palabra y no solo las ASCII en configuraciones regionales no ASCII.Otra alternativa:
Ese es un límite de palabras (uno que no es seguido por una secuencia de caracteres de palabras, una de las cuales se repite) seguido de 10 caracteres de palabras.
Cosas que posiblemente tenga en mente:
Babylonish
distingue entre mayúsculas y minúsculas, por lo que, por ejemplo, coincidiría, ya que todos los caracteres son diferentes a pesar de que hay dosB
s, una minúscula y una mayúscula (use-i
para cambiar eso).-w
,\w
y\b
, una palabra es una letra (ASCII solo para GNUgrep
por ahora , la[:alpha:]
clase de caracteres en su localidad si usa-P
y(*UCP)
), dígitos decimales o guiones bajos .c'est
(dos palabras según la definición francesa de una palabra) oit's
(una palabra según algunas definiciones inglesas de una palabra) orendez-vous
(una palabra según la definición francesa de una palabra) no se consideran una palabra.(*UCP)
, los caracteres de combinación Unicode no se consideran componentes de palabras, por lo quetéléphone
($'t\u00e9le\u0301phone'
) se considera como 10 caracteres, uno de los cuales no es alfa.défavorisé
($'d\u00e9favorise\u0301'
) coincidiría aunque tenga dosé
porque son 10 caracteres alfabéticos diferentes seguidos de una combinación de acento agudo (no alfa, por lo que hay un límite de palabras entre ele
y su acento).fuente
\w
aunque no coincide-
.De acuerdo ... aquí está la manera torpe para una cadena de cinco caracteres:
Debido a que no puede poner una referencia inversa en una clase de caracteres (por ejemplo
[^\1|\2]
), debe usar una vista previa negativa -(?!foo)
. Esta es una función PCRE, por lo que necesita el-P
interruptor.El patrón para una cadena de 10 caracteres será mucho más largo, por supuesto, pero hay un método más corto que usa una coincidencia de longitud variable ('. *') En la búsqueda anticipada:
Después de leer la respuesta esclarecedora de Stephane Chazelas, me di cuenta de que hay un patrón simple similar para esto que se puede usar a través del
-v
interruptor de grep :Dado que la verificación continúa un carácter a la vez, esto verá si algún carácter seguido es seguido por cero o más caracteres (
.*
) y luego una coincidencia para la referencia inversa.-v
invierte, imprime solo cosas que no coinciden con este patrón Esto hace que las referencias posteriores sean más útiles, ya que no se pueden negar con una clase de caracteres y significativamente:funcionará para identificar una cadena de cualquier longitud con caracteres únicos, mientras que:
no lo hará, ya que coincidirá con cualquier sufijo con caracteres únicos (por ejemplo,
abcabc
coincide porabc
el final yaaaa
pora
el final, por lo tanto, cualquier cadena). Esta es una complicación causada por las miradas de ancho cero (no consumen nada).fuente
(.)(?!.*\1)(.)(?!.*\2)(.)(?!.*\3)(.)(?!\4).
Si no necesita hacer todo en regex, lo haría en dos pasos: primero haga coincidir todas las palabras de 10 letras, luego filtrelas por su singularidad. La forma más corta que sé cómo hacer esto es en Perl:
Tenga en cuenta las
\W
anclas adicionales para asegurarse de que solo las palabras que tengan exactamente 10 caracteres de longitud coincidan.fuente
Otros han sugerido que esto no es posible sin varias extensiones a ciertos sistemas de expresión regular que de hecho no son regulares. Sin embargo, dado que el idioma que desea hacer coincidir es finito, es claramente regular. Para 3 letras de un alfabeto de 4 letras, sería fácil:
Obviamente, esto se sale de control con más letras y alfabetos más grandes. :-)
fuente
La opción
--perl-regexp
(breve-P
) de GNUgrep
utiliza expresiones regulares más potentes que incluyen patrones de anticipación. El siguiente patrón busca cada letra que esta letra no aparece en el resto de la palabra:Sin embargo, el comportamiento en tiempo de ejecución es bastante malo, ya que
\w*
puede tener una longitud casi infinita. Puede limitarse a\w{,8}
, pero eso también verifica más allá del límite de palabras de 10 letras. Por lo tanto, el siguiente patrón primero verifica la longitud de palabra correcta:Como archivo de prueba, he usado un archivo grande de ≈ 500 MB:
Actualizar:
No pude encontrar un cambio significativo en el comportamiento en tiempo de ejecución para un operador no codicioso (
\w*?
) o un operador posesivo ((...){10}+
). Un poco más rápido parece el reemplazo de la opción-w
:Una actualización de grep de la versión 2.13 a 2.18 fue mucho más efectiva. El archivo de prueba solo tomó ≈ 6 s.
fuente
\w{,8}?
) ayudó para algún tipo de entrada (aunque no de manera muy significativa). Buen uso de\g{-1}
para evitar el error grep de GNU.\g{-1}
, porque hace que el patrón sea más independiente de la ubicación. De esta forma, se puede usar como parte de un patrón más grande.Una solución de Perl:
pero no funciona con
o
probado con perl v5.14.2 y v5.18.2
fuente