/ / (Python) regex: hace coincidir todo lo que NO está en una lista (estática) de cadenas - python, regex

(Python) regex: hace coincidir todo lo que NO está en una lista (estática) de cadenas - python, regex

Digamos que tengo la lista (estática) ["DOG", "CAT", "LEOPARD"] (cuerdas de posibles longitudes diferentes).

Sé cómo construir la expresión regular que captura pares de animales separados por comas que pertenecen a esta lista:

from re import search
search("^(DOG|CAT|LEOPARD),(DOG|CAT|LEOPARD)$", "DOG,LEOPARD") #-> Match
search("^(DOG|CAT|LEOPARD),(DOG|CAT|LEOPARD)$", "LEOPARD,WHALE") #-> No match

Ahora quiero una expresión regular que coincida con los pares de animales donde ninguno de ellos pertenece a mi lista de animales. Usando el operador ficticio !, lo que quiero es:

from re import search
search("^!(DOG|CAT|LEOPARD),!(DOG|CAT|LEOPARD)$", "DOG,LEOPARD") #-> No match
search("^!(DOG|CAT|LEOPARD),!(DOG|CAT|LEOPARD)$", "CHIMP,WHALE") #-> Match

¿Existe tal operador?

Si no, ¿hay una manera simple de construir tales¿Un operador encadenando los existentes (estoy escribiendo un constructor de expresiones regulares, por lo que ni la legibilidad ni la longitud de la expresión regular son factores importantes aquí)?

Nota: Soy consciente de que le estoy pidiendo mucho a mi motor de expresión regular.

Nota 2: No me interesan las soluciones que no se basan en expresiones regulares, ya que este problema se integra en uno mucho más grande que ya estoy resolviendo con expresiones regulares (muy complejas).

Respuestas

2 para la respuesta № 1

En lugar de hacer esto usando expresiones regulares, puede usar conjuntos y probar la intersección:

>>> a = set(["DOG", "CAT", "LEOPARD"])
>>> b = set("DOG,LEOPARD".split(","))
>>> True if a.intersection(b) else False

1 para la respuesta № 2

¿Por qué no usar cadenas y funciones incorporadas en lugar de expresiones regulares?

def matcher(no, s):
return not any(word in no for word in set(s.split(",")))

Resultado:

>>> matcher({"DOG", "CAT", "LEOPARD"}, "DOG,LEOPARD")
False
>>> matcher({"DOG", "CAT", "LEOPARD"}, "CHIMP,WHALE")
True

1 para la respuesta № 3

Estas buscando miradas:

^(?!(?:DOG|CAT|LEOPARD),)[^,]+,(?!(?:DOG|CAT|LEOPARD)$)[^,]+$

Desglose del patrón:

^     assert position at start of string
(?!   assert the following text does NOT match...
(?:DOG|CAT|LEOPARD) ...one of these 3 words...
,   ...followed by a comma. The comma is essential, because it makes sure that the text
IS dog or cat or leopard. Without the comma, the regex would check if the text
STARTS WITH dog, cat or leopard.
)
[^,]+   if we"ve reached this point, we know the animal isn"t cat, dog or leopard. Match up
until the next comma.
,       consume the comma
(?!     same as before, except this time...
(?:DOG|CAT|LEOPARD)
$   ...assert end of string instead of comma
)
[^,]+
$