2015-01-21 13 views
5

Stiamo lavorando su un progetto in cui vogliamo che gli utenti siano in grado di utilizzare sia la sintassi emoji (come :smile:, :heart:, :confused:, :stuck_out_tongue:), così come le emoticon normali (come :), <3, :/, :p)Regex corrispondenti emoticon

ho problemi con la sintassi emoticon perché a volte si verificheranno queste sequenze di caratteri in:

  • stringhe normali o URL - http ://esempio. com
  • all'interno della sintassi emoji - :p encil:

Come posso trovare queste sequenze di caratteri emoticon ma non quando gli altri personaggi sono vicino a loro?

L'intera espressione regolare che sto utilizzando per tutte le emoticon è enorme, quindi ecco una versione trimed giù:

(\:\)|\:\(|<3|\:\/|\:-\/|\:\||\:p) 

Si può giocare con una demo di esso in azione qui: http://regexr.com/3a8o5

+0

Perché non dividerlo in più regex? Inoltre, ciò che si potrebbe fare è far corrispondere i limiti, ad esempio '/ \ b: \) \ b /' – elclanrs

+0

Se ricordo male, entrambi [Twemoji] (https://github.com/twitter/twemoji/) e [ Emojione] (https://github.com/Ranks/emojione/tree/master/lib/js) fornisce il codice JS per farlo con i loro set di immagini e ci sono dozzine di implementazioni della stessa cosa su Github, NPM, bower ecc. – Crissov

risposta

5

Partita emoji prima (a prendersi cura del: Matita: esempio) e poi verificare la presenza di uno spazio bianco estinzione o di ritorno a capo:

(\:\w+\:|\<[\/\\]?3|[\(\)\\\D|\*\$][\-\^]?[\:\;\=]|[\:\;\=B8][\-\^]?[3DOPp\@\$\*\\\)\(\/\|])(?=\s|[\!\.\?]|$) 

Questa espressione regolare corrisponde al seguente (emoji preferendo) tornando alla partita in corrispondenza del gruppo 1:

:(:) :P :p :O :3 :| :/ :\ :$ :* :@ 
:-(:-) :-P :-p :-O :-3 :-| :-/ :-\ :-$ :-* :[email protected] 
:^(:^) :^P :^p :^O :^3 :^| :^/ :^\ :^$ :^* :^@ 
): (: $: *: 
)-: (-: $-: *-: 
)^: (^: $^: *^: 
<3 </3 <\3 
:smile: :hug: :pencil: 

supporta anche la punteggiatura terminale come un delimitatore oltre allo spazio bianco.

si possono vedere maggiori dettagli e testare qui: https://regex101.com/r/aM3cU7/4

+0

Sì! Ho già selezionato la selezione delle emoticon ma la chiave qui è l'aggiunta di '(? = \ S | [\! \. \, \?] | $)' Alla fine della mia regex esistente. Grazie! –

+0

Aggiornato la mia demo regex con le aggiunte qui: http://regexr.com/3a91e –

+3

Quando si combina '(' o ')' si dovrebbe anche controllare che non faccia parte di un insieme valido di parentesi, per esempio non si Non voglio che questo corrisponda all'emoticon '8) qui:' blah blah bug (riprodotto su iOS 8) '. In breve, questo non è qualcosa che puoi gestire bene con espressioni regolari. –

1

I supponiamo che queste emoticon saranno comunemente usate con gli spazi prima e dopo. Quindi \s potrebbe essere quello che stai cercando, in quanto rappresenta uno spazio bianco.

Allora la tua espressione regolare sarebbe diventato

\s+(\:\)|\:\(|<3|\:\/|\:-\/|\:\||\:p)\s 
1

Fai un positive look-ahead for a space

([\:\<]-?[)(|\\/pP3D])(?:(?=\s)) 
|  |  |   | 
|  |  |   | 
|  |  |   |-> match last separating space 
|  |  |-> match last part of the emot 
|  |-> it may have a `-` or not 
|-> first part of the emoticon 

Dal momento che si sta utilizzando javascript, e non si ha accesso a guardare around:

/([\:\<]-?[)|\\/pP3D])(\s|$)/g.exec('hi :) ;D'); 

E quindi solo splice() la matrice risultante dall'ultima voce (th di al massimo probabilmente uno spazio)

0

Volete regex look-around per quanto riguarda la spaziatura.Un'altra risposta qui suggerito una positiva look-ahead, anche se mi piacerebbe andare a doppio negativo:

(?<!\S)(\:\)|\:\(|<3|\:\/|\:-\/|\:\||\:p)(?!\S) 

Mentre JavaScript non supporta (?<!pattern), look-behind can be mimicked:

test_string.replace(/(\S)?(\:\)|\:\(|<3|\:\/|\:-\/|\:\||\:p)(?!\S)/, 
        function($0, $1) { return $1 ? $0 : replacement_text; }); 

Tutto quello che ho fatto è stato prefisso il codice con (?<!\S) davanti e suffisso con (?!\S) sul retro. Il prefisso assicura che non si segua un carattere non di spazio vuoto, quindi le uniche voci iniziali valide sono spazi o niente (inizio della riga). Il suffisso fa la stessa cosa, assicurandoti di non essere seguito da un carattere non di uno spazio bianco. Vedi anche questo more thorough regex walk-through.

Uno dei commenti alla domanda stessa suggeriva i marcatori \b (limite di parole). Non li raccomando. In realtà, questo suggerimento farebbe il contrario di quello che vuoi; \b:/ corrisponderà effettivamente a http:// poiché esiste un limite di parole tra lo p e lo :. Questo tipo di ragionamento suggerisce \B (non un limite di parole), ad es. \B:/\B. Questo è più portabile (funziona praticamente con tutti i parser regex mentre i look-around non lo fanno), e in questo caso puoi sceglierlo, ma preferisco i look-around.

+0

Sto usando JavaScript e lookbehinds non sono supportati in JS :( –

+0

@ChrisBarr ah, buon punto Risolto usando una funzione per la chiamata di sostituzione.Vedi la modifica che ho appena fatto. –