2015-01-21 4 views
5

Мы работаем над проектом, где мы хотим, чтобы пользователи могли использовать синтаксис как Emoji (как :smile:, :heart:, :confused:, :stuck_out_tongue:), а также нормальные смайлики (как :), <3, :/, :p)Regex соответствие смайлики

у меня возникли проблемы с синтаксисом смайликов, потому что иногда эти последовательности символов будут происходить в:

  • нормальные строки или URL, - HTTP ://пример. ком
  • в синтаксисе Emoji - :p encil:

Как я могу найти эти смайлик последовательности символов, но не тогда, когда другие символы рядом с ними?

Весь регулярное выражение я использую для всех смайлов огромен, так вот trimed вниз версия:

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

Вы можете играть с демо его в действии здесь: http://regexr.com/3a8o5

+0

Почему бы не разделить его на несколько регулярных выражений? Кроме того, что вы можете сделать, это совпадение с границами, например '/ \ b: \) \ b /' – elclanrs

+0

Если я правильно помню, как [Twemoji] (https://github.com/twitter/twemoji/), так и [ Emojione] (https://github.com/Ranks/emojione/tree/master/lib/js) предоставляют JS-код для этого с их наборами изображений, и есть десятки реализаций того же самого на Github, NPM, bower и т. Д. – Crissov

ответ

5

Match смайликов первый (позаботиться о: карандаш: пример), а затем проверить завершающего пробел или символ новой строки:

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

Это регулярное выражение соответствует следующей (предпочитающих смайлик) возвращая матч в соответствии группы 1:

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

Он также поддерживает терминальные знаки препинания в качестве разделителя в дополнении к белому пространству.

Вы можете увидеть более подробную информацию и проверить его здесь: https://regex101.com/r/aM3cU7/4

+0

Да! У меня уже есть выбор эмоций, но ключ здесь добавляет '(? = \ S | [\! \. \, \?] | $)' В конце моего существующего регулярного выражения. Благодаря! –

+0

Обновлено мое демо-приложение regex с дополнениями здесь: http://regexr.com/3a91e –

+3

При совпадении '(' или ')' вы также должны проверить, что он не является частью допустимого набора круглых скобок, например, вы надеваете 't хочу, чтобы это соответствовало '8)' emicon здесь: 'ошибка blah (воспроизведена на iOS 8)'. Короче говоря, это действительно не то, с чем вы можете хорошо справиться с регулярным выражением. –

1

I предположим, что эти смайлики будут обычно использоваться с пробелами до и после. Тогда \s может быть тем, что вы ищете, поскольку оно представляет собой пробел.

Тогда ваше регулярное выражение станет

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

Сделать 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 

Поскольку вы используете JavaScript, и вы не имеете доступа смотреть обходные:

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

А потом только splice() результирующий массив из его последней записи (th в наиболее вероятно, пространство)

0

Вы хотите регулярные выражения выглядят обходных относительно расстояния.Другой ответ здесь предложил положительный смотреть вперед, хотя я бы дважды отрицательна:

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

Хотя JavaScript не поддерживает (?<!pattern), look-behind can be mimicked:

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

Все, что я сделал, это префикс кода с (?<!\S) спереди и суффикс с (?!\S) сзади. Префикс гарантирует, что вы не следуете символу без пробелов, поэтому единственными действительными ведущими элементами являются пробелы или ничего (начало строки). Суффикс делает то же самое, гарантируя, что за вами не будет следовать символ без пробелов. См. Также это more thorough regex walk-through.

Один из комментариев к самому вопросу предлагал маркеры \b (граница слова). Я не рекомендую их. Фактически, это предложение сделало бы противоположное тому, что вы хотите; \b:/ действительно соответствует http://, так как между p и : есть граница слов. Такое рассуждение предложило бы \B (а не границу слова), например. \B:/\B. Это более портативно (он работает почти со всеми синтаксическими анализаторами регулярных выражений, в то время как обходные круги - нет), и вы можете выбрать его в этом случае, но я предпочитаю внешний вид.

+0

Я использую JavaScript и lookbehinds не поддерживаются в JS :( –

+0

@ChrisBarr ах, хорошая точка. Решено использовать функцию для вызова замены. См. Редактирование, которое я только что сделал. –

Смежные вопросы