Capturando emoticones usando expresiones regulares en python

Me gustaría tener un patrón de expresiones regulares para hacer coincidir los emoticons “:)”, “:(“. También debería capturar los emoticons repetidos como “:) :)”, “:) :(” pero filtrar la syntax no válida como “:( (“.

Tengo esto conmigo, pero coincide con “:( (”

bool( re.match("(:\()",str) ) 

Tal vez me esté perdiendo algo obvio aquí, y me gustaría algo de ayuda para esta tarea aparentemente simple.

Creo que finalmente “hizo clic” exactamente lo que estás preguntando aquí. Echa un vistazo a lo siguiente:

 import re smiley_pattern = '^(:\(|:\))+$' # matches only the smileys ":)" and ":(" def test_match(s): print 'Value: %s; Result: %s' % ( s, 'Matches!' if re.match(smiley_pattern, s) else 'Doesn\'t match.' ) should_match = [ ':)', # Single smile ':(', # Single frown ':):)', # Two smiles ':(:(', # Two frowns ':):(', # Mix of a smile and a frown ] should_not_match = [ '', # Empty string ':(foo', # Extraneous characters appended 'foo:(', # Extraneous characters prepended ':( :(', # Space between frowns ':( (', # Extraneous characters and space appended ':((' # Extraneous duplicate of final character appended ] print('The following should all match:') for x in should_match: test_match(x); print('') # Newline for output clarity print('The following should all not match:') for x in should_not_match: test_match(x); 

El problema con su código original es que su expresión regular es incorrecta: (:\() . Vamos a desglosarla.

Los paréntesis externos son una “agrupación”. Son a lo que se referiría si hiciera un reemplazo de cadena, y se usan para aplicar operadores de expresiones regulares en grupos de caracteres a la vez. Entonces, realmente estás diciendo:

  • ( comenzar un grupo
    • :\( … hacer regex cosas …
  • ‘)’ terminar el grupo

El : no es un carácter reservado de expresiones regulares, por lo que es sólo dos puntos. El \ es, y significa “el siguiente carácter es literal, no un operador de expresiones regulares”. Esto se llama una “secuencia de escape”. Completamente analizado en inglés, su expresión regular dice

  • ( comenzar un grupo
    • : un personaje de dos puntos
    • \( un carácter de paréntesis izquierdo
  • ) terminar el grupo

El regex que utilicé es un poco más complejo, pero no está mal. Vamos a desglosarlo: ^(:\(|:\))+$ .

^ y $ significan “el principio de la línea” y “el final de la línea” respectivamente. Ahora tenemos …

  • ^ comienzo de linea
    • (:\(|:\))+ … hacer regex cosas …
  • $ fin de línea

… así que solo hace coincidir las cosas que comprenden la línea completa, no simplemente ocurre en el medio de la cadena.

Sabemos que ( y ) denotamos una agrupación. + significa “uno de más de estos”. Ahora tenemos:

  • ^ comienzo de linea
  • ( comenzar un grupo
    • :\(|:\) … hacer regex cosas …
  • ) terminar el grupo
  • + coincide con uno o más de esto
  • $ fin de línea

Finalmente, está la | operador (tubería). Significa “o”. Entonces, aplicando lo que sabemos por encima sobre los personajes que escapan, estamos listos para completar la traducción:

  • ^ comienzo de linea
  • ( comenzar un grupo
    • : un personaje de dos puntos
    • \( un carácter de paréntesis izquierdo
  • | o
    • : un personaje de dos puntos
    • \) un carácter de paréntesis derecho
  • ) terminar el grupo
  • + coincide con uno o más de esto
  • $ fin de línea

Espero que esto ayude. Si no, hágamelo saber y estaré encantado de editar mi respuesta con una respuesta.

Quizás algo como:

 re.match('[:;][)(](?![)(])', str) 

Probar (?::|;|=)(?:-)?(?:\)|\(|D|P) . No lo he probado extensivamente, pero parece coincidir con los correctos y no más …

 In [15]: import re In [16]: s = "Just: to :)) =) test :(:-(( ():: :):) :(:( :P ;)!" In [17]: re.findall(r'(?::|;|=)(?:-)?(?:\)|\(|D|P)',s) Out[17]: [':)', '=)', ':(', ':-(', ':)', ':)', ':(', ':(', ':P', ';)'] 

Obtuve la respuesta que estaba buscando de los comentarios y respuestas publicados aquí.

 re.match("^(:[)(])*$",str) 

Gracias a todos.

 re.search(r"^[(>:#;=*[8|\-B/\\@<~^%$LXoO0}3Vb][a-zA-Z0-9',v(>:#;=*+[8|\-B/\\@<~^%$LXoO0}3Vb)]*$",any_emoji) 

Coincide con la mayoría de los emojis en este sitio http://www.emoticonr.com/filter/a ¡ Buena suerte!