2015-01-21 10 views
5

pracujemy nad projektem, gdzie chcemy, aby użytkownicy mogli korzystać zarówno składni Emotikon (jak :smile:, :heart:, :confused:, :stuck_out_tongue:), jak również normalne emotikony (jak :), <3, :/, :p)Regex dopasowania emotikony

mam problemy ze składnią emotikon, bo czasami te sekwencje znaków wystąpią w:

  • normalnych ciągi lub URL - http ://np. com
  • w składni emotikonów - :p encil:

Jak mogę znaleźć te sekwencje znaków emotikony, ale nie wtedy, gdy inne postacie są blisko nich?

Cały regex używam dla wszystkich emotikonów jest ogromny, więc o to trimed dół wersja:

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

Możesz grać z demo go w akcji tutaj: http://regexr.com/3a8o5

+0

Dlaczego nie podzielić go na kilka wyrażeń regularnych? Możesz również dopasować do granic, na przykład '/ \ b: \) \ b /' – elclanrs

+0

Jeśli dobrze pamiętam, zarówno [Twemoji] (https://github.com/twitter/twemoji/) i [ Emojione] (https://github.com/Ranks/emojione/tree/master/lib/js) dostarcza kod JS, aby to zrobić z ich zestawami obrazów i istnieją dziesiątki implementacji tego samego na Github, NPM, altance itp. – Crissov

Odpowiedz

5

emotikonów Mecz pierwszy (aby zadbać o: ołówkiem: przykład), a następnie sprawdzić, czy kończąca spacji lub nowej linii:

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

Ten regex pasuje następujący (preferując emotikony) zwrócenie dopasowania w dopasowanej grupie 1:

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

Obsługuje również interpunkcję terminalową jako ogranicznik oraz białe znaki.

można zobaczyć więcej szczegółów i przetestować go tutaj: https://regex101.com/r/aM3cU7/4

+0

Tak! Mam już wybór emotikon, ale kluczem tutaj jest dodanie '(? = \ S | [\! \. \, \?] | $)' Na końcu mojego istniejącego wyrażenia regularnego. Dzięki! –

+0

Zaktualizowałem moje demo regex z dodatkami tutaj: http://regexr.com/3a91e –

+3

Podczas dopasowywania '(' lub ')' należy również sprawdzić, czy nie jest częścią prawidłowego zestawu nawiasów, na przykład nie chcę aby to pasowało do '8)' emotikonu tutaj: 'bla bla bla (reprodukowanego na iOS 8)'. W skrócie, to naprawdę nie jest coś, z czym można sobie poradzić z regex. –

1

I załóżmy, że te emotikony będą zwykle używane ze spacjami przed i po. Wtedy może być to, czego szukasz, ponieważ reprezentuje białą przestrzeń.

Wtedy twoje regex staną

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

Zrób 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 

Ponieważ używasz JavaScript, a nie masz dostępu do zajrzeć arounds:

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

A następnie po prostu splice() wynikowa tablica z ostatniego wpisu (th w najbardziej chyba spacja)

0

Chcesz regex przeglądowej arounds dotyczących odstępów.Kolejna odpowiedź tutaj sugeruje pozytywny look-ahead, chociaż pójdę podwójnie negatywny:

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

Podczas JavaScript nie obsługuje (?<!pattern), look-behind can be mimicked:

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

Ja tylko prefiks kodu z numerem (?<!\S) z przodu i sufiksem z numerem (?!\S) z tyłu. Prefiks zapewnia, że ​​nie podążasz za znakiem spacji, więc jedynymi ważnymi wpisami wiodącymi są spacje lub nic (początek linii). Przyrostek robi to samo, upewniając się, że nie następuje po nim żadna spacja. Zobacz także ten more thorough regex walk-through.

Jednym z komentarzy do samego pytania było sugerowanie znaczników \b (granica słowa). Nie polecam tych. W rzeczywistości ta sugestia byłaby przeciwieństwem tego, czego chcesz; \b:/ rzeczywiście będzie pasować do http://, ponieważ istnieje granica wyrazów między p i :. Ten rodzaj rozumowania sugerowałby, że nie jest to granica wyrazów, np. \B. \B:/\B. Jest to bardziej przenośne (działa prawie ze wszystkimi parserami regex, a rozglądasz się za nimi), i możesz wybrać to w tym przypadku, ale wolę rozejrzeć się.

+0

Używam JavaScript i lookbehinds nie są obsługiwane w JS :( –

+0

@ ChrisBarr ah, dobry punkt. Rozwiązano za pomocą funkcji do zastąpienia połączenia. Zobacz edytowaną właśnie edycję. –