2015-01-21 20 views
5

Wir sind an einem Projekt arbeiten, wo wir wollen Benutzer in der Lage sein, sowohl die Emoji-Syntax zu verwenden (wie :smile:, :heart:, :confused:, :stuck_out_tongue:) sowie normale Emoticons (wie :), <3, :/, :p)Regex passende Emoticons

ich habe Probleme mit der Emoticon-Syntax, weil manchmal in diese Zeichenfolgen auftreten:

  • normale Strings oder URL - http ://example. com
  • innerhalb der Emoji-Syntax - :p encil:

Wie kann ich diese Emoticon Zeichenfolgen zu finden, aber nicht, wenn andere Zeichen in der Nähe von ihnen sind?

Die gesamte regex Ich bin für alle Emoticons ist riesig, also hier eine trimed abgespeckte Version:

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

können Sie sich hier mit einer Demo davon in Aktion spielen: http://regexr.com/3a8o5

+0

Warum nicht in mehreren Regexes aufteilen? Auch was Sie tun könnten, ist mit den Grenzen übereinstimmen, zum Beispiel '/ \ b: \) \ b /' – elclanrs

+0

Wenn ich mich richtig erinnere, sowohl [Twemoji] (https://github.com/twitter/twemoji/) und [ Emojione] (https://github.com/Ranks/emojione/tree/master/lib/js) stellen JS - Code zur Verfügung, um das mit ihren Bildsätzen zu tun, und es gibt Dutzende von Implementierungen derselben Sache auf Github, NPM, Bower etc – Crissov

Antwort

5

Spiel Emoji ersten (kümmern sich um den: Bleistift: Beispiel) und dann prüfen, ob ein Abschluss Leerzeichen oder Newline:

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

Diese Regex entspricht den folgenden (lieben Emoji) Zurückgeben des Matches in der übereinstimmenden Gruppe 1:

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

Es unterstützt auch Terminal Interpunktion als Trennzeichen zusätzlich zu Leerraum.

können Sie weitere Details sehen und es hier testen: https://regex101.com/r/aM3cU7/4

+0

Ja! Ich habe bereits die Emoticon Auswahl funktioniert, aber der Schlüssel hier ist '(? = \ S | [\! \. \, \?] | $)' Am Ende meiner bestehenden Regex. Vielen Dank! –

+0

Meine Regex-Demo mit den Ergänzungen hier aktualisiert: http://regexr.com/3a91e –

+3

Wenn Sie '(' oder ')' zusammenpassen, sollten Sie auch überprüfen, dass es nicht Teil einer gültigen Klammer ist, zum Beispiel Sie nicht Ich will das hier nicht zum '8)' Emoticon passen: 'blah blah bug (reproduziert auf iOS 8)'. Kurz gesagt, das ist wirklich nicht etwas, was Sie gut mit Regex umgehen können. –

1

I Angenommen, diese Emoticons werden normalerweise mit Leerzeichen davor und danach verwendet. Dann ist \s vielleicht das, was Sie suchen, da es einen Leerraum darstellt.

Dann würde Ihre regex

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

eine 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 

Stellen werden Da Sie Javascript verwenden, und Sie haben keinen Zugang Arounds suchen:

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

Und dann einfach splice() das resultierende Array aus seinem letzten Eintrag (th bei den höchstwahrscheinlich ein Raum)

0

Sie in Bezug auf Abstand regex Look-arounds wollen.Ein andere Antwort vorgeschlagen hier einen positiven Vorgriff, obwohl ich gehen würde doppelt negativ:

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

Während JavaScript nicht unterstützt (?<!pattern), look-behind can be mimicked:

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

Alles, was ich tat, war Präfix Code mit (?<!\S) vorne und Suffix mit (?!\S) auf der Rückseite. Das Präfix stellt sicher, dass Sie nicht einem Nicht-Leerzeichen folgen, daher sind die einzigen gültigen führenden Einträge Leerzeichen oder nichts (Zeilenbeginn). Das Suffix macht das Gleiche und stellt sicher, dass Ihnen kein Nicht-Leerzeichen folgt. Siehe auch diese more thorough regex walk-through.

Einer der Kommentare zu der Frage selbst schlug \b (Wortgrenze) -Marker vor. Ich empfehle diese nicht. In der Tat würde dieser Vorschlag das Gegenteil von dem tun, was Sie wollen; \b:/ wird in der Tat http:// übereinstimmen, da es eine Wortgrenze zwischen und : gibt. Diese Art der Argumentation würde \B (keine Wortgrenze) vorschlagen, z.B. \B:/\B. Dies ist portabler (es funktioniert mit so ziemlich allen Regex-Parsern, während das bei Umwegen nicht funktioniert), und Sie können es in diesem Fall wählen, aber ich bevorzuge die Umwege.

+0

Ich benutze JavaScript und Lookbehinds werden in JS nicht unterstützt :( –

+0

@ChrisBarr ah, guter Punkt. Gelöst mit einer Funktion für den Ersatz Anruf. Siehe die Bearbeitung, die ich gerade gemacht habe. –