Expresión regular de Python: Alternancia para conjuntos de palabras

Sabemos que \ba\b|\bthe\b coincidirá con la palabra ” a ” o ” the
Quiero construir una expresión regular para que coincida con un patrón como

a / la / una / razones de / de

Lo que significa que quiero hacer coincidir una cadena s contiene 3 palabras:

  • la primera palabra de s debe ser ” a “, ” the ” o ” one
  • la segunda palabra debe ser ” razón ” o ” razones
  • la tercera palabra de s debe ser ” para ” o ” de

La expresión regular \ba\b|\bthe\b|\bone\b \breason\b|reasons\b \bfor\b|\bof\b no ayuda.

¿Cómo puedo hacer esto? Por cierto, yo uso python. Gracias.

Una característica interesante del módulo de expresiones regulares es la lista nombrada. Con él, no tienes que incluir varias alternativas separadas por | en un grupo no capturador. Solo necesita definir la lista antes y referirse a ella en el patrón por su nombre. Ejemplo:

 import regex words = [ ['a', 'the', 'one'], ['reason', 'reasons'], ['for', 'of'] ] pattern = r'\m \L \s+ \L \s+ \L \M' p = regex.compile(pattern, regex.X, word1=words[0], word2=words[1], word3=words[2]) s = 'the reasons for' print(p.search(s)) 

Incluso si esta característica no es esencial, mejora la legibilidad.

Puede lograr algo similar con el módulo re si une elementos con | antes de:

 import re words = [ ['a', 'the', 'one'], ['reason', 'reasons'], ['for', 'of'] ] words = ['|'.join(x) for x in words] pattern = r'\b ({}) \s+ ({}) \s+ ({}) \b'.format(*words) p = re.compile(pattern, re.X) 

Debe usar un grupo de captura para negarse a mezclar los OR ( | )

 (\ba\b|\bthe\b|\bone\b) (\breason\b|reasons\b) (\bfor\b|\bof\b) 

Y luego, como una forma más elegante, puede colocar los límites de las palabras alrededor de los grupos. También tenga en cuenta que cuando está usando el espacio en su expresión regular alrededor de las palabras, no hay necesidad de usar el límite de las palabras. Y por reasons y reason puede hacer la última s opcional con ? . Y tenga en cuenta que si no desea que sus palabras coincidan en grupos separados, puede hacer que sus grupos formen un grupo de captura sin :? .

 \b(?:a|the|one) reasons? (?:for|of)\b 

O usa el grupo de captura si quieres las palabras en grupo:

 \b(a|the|one) (reasons?) (for|of)\b 

El modificador de expresión regular A|B significa que “si A o B coinciden, entonces todo coincide”. En su caso, la expresión regular resultante coincide si / donde alguna de las siguientes 5 expresiones regulares coinciden:

  • \ba\b
  • \bthe\b
  • \bone\b \breason\b
  • reasons\b \bfor\b
  • \bof\b

Para limitar la medida en que | aplica, usa la agrupación no captura para esto, es decir (?:something|something else) . Además, para tener una s opcional al final de la reason , no necesita usar la alteración; esto es exactamente igual a las reasons? .

Así obtenemos las \b(?:a|the|one) reasons? (?:for|of)\b la expresión regular \b(?:a|the|one) reasons? (?:for|of)\b \b(?:a|the|one) reasons? (?:for|of)\b .

Tenga en cuenta que no es necesario utilizar la palabra operadores de límite \b dentro de la expresión regular, solo al principio y al final (de lo contrario, coincidiría con algo como everyone reasons forever ).

Usa paréntesis para agrupar:

 '\b(a|the|one) reason(|s) (for|of)\b' 

Dejé afuera la oración interna \b ‘s ya que los espacios los implican: Un espacio que sigue a una letra es siempre un límite de palabra. En general deberías poner el \b fuera de las alternativas; Es más corto y más legible.

Si importa, puede usar “grupos que no capturan” en todos los motores de expresiones regulares modernos: Use (?:stuff) lugar de (stuff) . Pero si no es importante para sus usos, o si necesita saber cuál de las alternativas de palabras están realmente presentes, vaya con parens simples.

Como entiendo que quieres un regex como este:

 (?:a|the|one)\s+(?:reason|reasons)\s+(?:for|of) 

Es tan simple, solo combínalos usando grupos .

ver: DEMO

Nota Su requisito anterior, su sonido no es tan estricto para mí, en caso de que desee modificar algo por su cuenta, consideremos la siguiente explicación.

Explicación

(?:abc|ijk|xyz)

Cualquier palabra abc , ijk o xyz agrupada por un grupo que no sea de captura (?:...) significa que esta palabra no capturará a la variable de expresión regular $1 , $2 , $3 , ...

\s+

Este es un delimitador de palabras que aquí lo configuro como cualquier espacio, + representa 1 o más.