2010-03-05 22 views
5

¿Hay alguna manera de obtener una sola expresión regular para satisfacer esta condición?¿cómo incluyo un booleano Y dentro de una expresión regular?

Busco a una "palabra" que tiene tres cartas del conjunto mbipi, cualquier orden, sino que debe contener un I.

decir.

re.match ("[MBDPI] {3}", foo) y "I" en foo

Así que esto es el resultado correcto (en Python usando el módulo re), pero que puede obtener esta información de una sola expresión regular?

>>> for foo in ("MBI", "MIB", "BIM", "BMI", "IBM", "IMB", "MBD"): 
...  print foo, 
...  print re.match("[MBDPI]{3}", foo) and "I" in foo 
MBI True 
MIB True 
BIM True 
BMI True 
IBM True 
IMB True 
MBD False 

con regex Sé que puedo usar | como un operador OR booleano, pero ¿hay un AND booleano equivalente?

o tal vez necesito un poco de búsqueda hacia adelante o hacia atrás?

+0

También puede buscar el carácter 'I' con str.find(). Fuente: http://docs.python.org/library/stdtypes.html#str.encuentra – Dor

Respuesta

2

O es lo único que puede hacer:

\b(I[MBDPI]{2}|[MBDPI]I[MBDPI]|[MBDPI]{2}I)\b 

El carácter \b coincide con un límite de palabra de anchura cero. Esto garantiza que coincida con algo que tiene exactamente tres caracteres de longitud.

De lo contrario, se está cumpliendo con los límites de lo que puede hacer un regular language.

Una alternativa es hacer coincidir:

\b[MBDPI]{3}\b 

captura de ese grupo y luego buscar un I.

Editar: en aras de tener una respuesta completa, voy a adapto Jens' answer que utiliza Testing The Same Part of a String for More Than One Requirement:

\b(?=[MBDPI]{3}\b)\w*I\w* 

con los controles de límite de palabra para asegurar que es sólo tres caracteres de longitud.

Esto es un poco más de una solución avanzada y aplicable en más situaciones, pero generalmente estoy a favor de lo que es más fácil de leer (siendo la versión "o" imho).

3

Puede falsificar booleanos AND usando lookaheads. De acuerdo con http://www.regular-expressions.info/lookaround2.html, esto funcionará para su caso:

"\b(?=[MBDPI]{3}\b)\w*I\w*" 
+0

Probablemente necesite verificaciones de límites de palabras, pero de lo contrario +1, solución inteligente. – cletus

+0

Voy a editar eso en ... – Jens

+0

excelente enlace, gracias. – user213043

2

Usted podría utilizar búsqueda hacia delante para ver si un I está presente:

(?=[MBDPI]{0,2}I)[MBDPI]{3} 
0

con expresiones regulares Sé que puedo usar | como un operador OR booleano, pero ¿hay un AND booleano equivalente?

A y B = no (no A o no B) = ([^ A] |?! [^ B])

A y B son expresiones que realmente pueden tener miembros en común.

Cuestiones relacionadas