Сегодняшний пост является продолжением Части 1 о семантике эмодзи.

🙀🔝На прошлой неделе Instagram начал поддерживать смайлики внутри хэштегов. В Пятницу мы говорили о росте использования эмодзи в Instagram и о том, как узнать семантику текста. Сегодняшний пост будет посвящен инженерным деталям реализации хэштегов эмодзи - казалось бы, простому изменению регулярного выражения, которое превратилось в пугающее путешествие через темные глубины юникода👺.

Откуда берутся хэштеги?

Когда к фотографии добавляется подпись или комментарий, сервер Instagram анализирует хэштеги с помощью регулярного выражения, а затем индексирует медиафайлы по хэштегу. Регулярное выражение совместно используется нашими клиентами (Интернет, Android, iOS), которые используют его для связывания тегов в заголовках и комментариях.

До хэштегов эмодзи регулярное выражение тега Instagram выглядело примерно так:

(?<<<<!>&)#(\w+)

Где \w соответствует всем подобным словам символам. Похоже, нам просто нужно добавить действительные символы эмодзи в список, развернуть новые двоичные файлы Instagram и затем положить конец этому 😏. В действительности оказывается, что даже простое изменение регулярного выражения может быть безумно сложным.

Справочная информация по Unicode

Чтобы полностью понять этот пост, вам понадобится минимальный опыт работы с Unicode. Вот краткий обзор.

В Unicode символы (латинский алфавит, кириллица, эмодзи и т. Д.) Представлены с помощью различных кодовых точек или чисел. Символы разных языков перечислены в стандарте Unicode. Компьютеры выражают эти числа с помощью различных кодировок. Большинству разработчиков программного обеспечения необходимо знать о трех:

  • UTF-8: выражает кодовые точки Unicode как последовательность байтов переменной длины. Символы в нижних диапазонах кодовых точек, такие как английский текст, могут быть выражены одним байтом, а символы в более высоких диапазонах могут занимать до четырех.
  • UTF-16: также выражает кодовые точки Unicode как последовательность байтов переменной длины. Эти последовательности составляют либо два байта (для диапазонов более низких кодовых точек), либо четыре байта (для диапазонов более высоких кодовых точек). Более высокие диапазоны кодируются с использованием двух 16-битных единиц, называемых «суррогатными парами».
  • UTF-32: последовательное выражение кодовых точек Unicode в виде четырехбайтовой последовательности.

UTF-16 - одна из самых сложных кодировок из-за наличия суррогатных пар. К сожалению, это также собственная кодировка для Objective-C, Java и Python (серия 2.x под определенными флагами компилятора).

Первая попытка

Инженерная философия Instagram заключается в том, чтобы сначала делать простые вещи. Я начал с чтения статьи в Википедии об эмодзи, которая заставила меня поверить, что все эмодзи представляют собой отдельные кодовые точки Unicode в одном из пяти блоков Unicode: разные символы и пиктограммы, смайлики, символы транспорта и карты, разные символы и дингбаты. Наивно, я написал регулярное выражение, которое соответствовало каждому диапазону индивидуально. Что-то вроде:

[\U0001F300-\U0001F5FF\U0001F600-\U0001F64F\U0001F680-\U0001F6FF\u2600-\u26FF\u2700–\u27BF]

Во время тестирования на iOS я смог пометить некоторые из моих любимых смайлов, например 💩 и 🍦. К сожалению, более глубокое тестирование нарушило мои предположения ...

Что идет не так и проект стандарта TR51

❤️ не сработало. 🇺🇸 не сработало. Даже смайлик со стрелкой ⬆️➡️⬇️⬅️ не сработал. Как я выяснил, этого недостаточно для соответствия определенным диапазонам смайлов для персонажей, потому что:

  • Некоторые смайлы состоят из нескольких кодовых точек в Юникоде. Например, смайлы флагов состоят из двух кодовых точек, обозначающих аббревиатуры стран из стандарта ISO 3166–1. Хотя iOS не реализовала флаг Гренландии, вы все равно можете выразить его с помощью букв G и L.
  • Клавиатуры эмодзи iOS выражают некоторые эмодзи в так называемых вариантных формах. Смайлик, например ❤️, будет выражен с помощью одной кодовой точки, соответствующей сердцу, за которой следует кодовая точка селектора вариантов, которая выбирает конкретный глиф для представления сердца. Теоретически может быть до 16 вариантов форм для любого смайлика с одним кодом. Некоторые эмодзи находятся за пределами этих блоков юникода. Например, идеограммы CJK 🈹🈶🈵🈳Emoji еще не стандартизированы, и поиск этих проблем требует большого количества проб и ошибок.

К счастью, я наткнулся на проект технического отчета TR51 по эмодзи, в котором задокументировано большинство вариантов, представленных в iOS и Android. Черновик даже поставляется с серией файлов данных, в которых перечислены общие смайлы для iOS и Android.

Генерация регулярных выражений с помощью кода

В черновике TR51 указано 1245 смайлов, что исключает возможность написания регулярных выражений от руки. Вместо этого я написал сценарий, который анализирует точки кода из списка и создает минимальное регулярное выражение, используя диапазоны символов. Для таких языков, как Objective-C, этот подход прекрасно работает. К сожалению, на сервере Instagram работает Python 2.7, из-за которого некоторые внутренние данные о кодировке символов выявляются наружу.

Различия в кодировании: перенос Python в астральный план ♉️

Python 2.x может быть скомпилирован как в широком режиме (с внутренним использованием UTF-32), так и в узком режиме (с внутренним использованием UTF-16). Как обсуждалось, UTF-16 представляет символы из диапазонов высоких кодовых точек (юмористически известных как астральный план) с использованием пары двухбайтовых последовательностей, называемых суррогатными парами. В узких сборках Python четырехбайтовые escape-последовательности Unicode не допускаются в качестве диапазонов символов регулярного выражения. Таким образом, вместо сопоставления блока смайликов используйте что-то разумное, например:

[\U0001F600-\U0001F64F]

Мы должны использовать совпадение суррогатной пары без диапазона, например:

(\uD83D[\uDE00-\uDE4F])

😭😭😭

Различия в синтаксисе

😳Регулярное выражение для хэштегов Instagram охватывает множество кодовых баз, включая наших клиентов (Java, Javascript, Objective-C), сервер (Python) и данные (HiveQL, C ++). Экранирование Unicode работает по-разному в разных языках, заставляя наш сценарий генерации регулярных выражений иметь несколько выходов. Особо следует отметить: Java 7 была первым выпуском, который включал экранирование символов Юникода астрального плана. Синтаксис экранирования допустим только в регулярных выражениях и не может использоваться для экранирования строк. Например, вы можете сопоставить U + 0001F600 с шаблоном \ x {1F600}. Поскольку эта новая функция доступна не во всех версиях Android, мы компилируем шаблон в блоке try {} catch {}, возвращаясь к устаревшему списку смайликов с низким диапазоном в случае ошибки.

Objective-C поддерживает экранирование Unicode для символов астрального плана в строках с \ U0001F600. К сожалению, этот синтаксис не работает в диапазоне ASCII, вызывая смесь другого синтаксиса \ xf6. Некоторые печатаемые символы нельзя указывать в шестнадцатеричной последовательности, и их необходимо напрямую встраивать в строку.

Версии ECMAscript (Javascript) до 6 имеют ту же суррогатную пару и проблемы двухбайтового экранирования, что и Python, что приводит к аналогичному регулярному выражению.

Различия в сопоставлении с образцом

Что означает \w в регулярном выражении? В мире ASCII \ w соответствует латинским «словесным» символам, но в мире Unicode технический стандарт UTS 18 рекомендует, чтобы \w соответствовал цифрам, алфавитным символам, общей категории «метка» и двум категориям, называемым «Пунктуация коннектора» и «Соединение». Контроль." Последние две категории используются в некоторых эмодзи, но языки программирования реализуют это по-разному. Objective-C в iOS 8.3 будет соответствовать \ w с U + 200d и U + fe0f. Python не соответствует ни тому, ни другому. Примечательно, что Java JRE (8.0) не соответствует ни одному, в то время как среда выполнения Android Java (уровень API 16) соответствует только U + fe0f.

Таким образом, в зависимости от платформы мы должны расширить разрешенный набор символов, включив в него специальные непечатаемые символы 👎

Новые эмодзи в iOS 8.3

iOS 8.3 вышла во время разработки эмодзи с хэштегом и добавила новые типы. В частности, Apple предоставила нам широкий выбор оттенков кожи и семейных вариантов. Оба они требуют нескольких кодовых точек Unicode, что требует дополнительных символов в конце регулярных выражений:

  • Варианты оттенка кожи 🎅🏻🎅🏼🎅🏽🎅🏾🎅🏿. iOS предлагает варианты тона кожи для существующих смайлов, таких как Санта-Клаус (U + 1F385). Они реализованы путем объединения смайликов с персонажем «фицпатрик» тона кожи из диапазона U + 1F3FB-U + 1F3FF. Из-за реализаций более старые выпуски и другие платформы будут отображать эмодзи как два отдельных символа (🎅, 🏻).
  • Разнообразные семьи 👩‍👩‍👧‍👦. iOS поддерживает множество различных вариантов семьи (пол, количество детей). Они реализованы в виде отдельных кодовых точек Unicode для каждого члена семейства, соединенных вместе соединяющим символом нулевой ширины unicode U + 200D. Это означает, что семейные эмодзи реализованы с использованием до 7 кодовых точек Юникода, которые буквально означают каждого члена семьи: женщина-женщина-девочка-мальчик. В более старых версиях и других платформах вы увидите каждого члена семьи индивидуально (👩, 👩, 👧, 👦)
  • Разнообразные поцелуи 👨‍❤️‍💋‍👨. Как и в случае с разными семьями, поцелуи между однополыми парами реализуются с использованием пяти кодовых точек Юникода, соединенных вместе с помощью U + 200D. Эти смайлики для поцелуев буквально означают один поцелуй, смайлик-сердце с вариантом выбора символа, смайлики губ, а затем еще один поцелуй. В более старых версиях и других платформах каждая часть будет выделена явно (👨‍, ❤️‍, 💋‍, 👨)

Моделирование решений

Варианты эмодзи поднимают некоторые сложные вопросы моделирования относительно того, что представляет собой хэштег. На сегодняшний день Instagram создал новый хэштег для каждой отдельной последовательности Unicode. Но как насчет вариантов смайликов? Следует ли индексировать фотографии из группы в категории? Можно ли смешивать символы, не являющиеся смайликами, с смайликами?

Начав с простого, мы посчитали, что на плакатах может быть удивительно видеть # 🎅🏻 фотографии под # 🎅, поэтому мы проиндексировали их отдельно. Если нам нужно изменить наше решение, проще объединить варианты в рамках единственного родителя, чем разбить родительский элемент на разные части.

Мы обсуждали, разрешить ли смешивание эмодзи и сценария вместе. Допуская более широкое выражение, он также создает крайние случаи при добавлении эмодзи в конец существующих хэштегов, таких как # tbt👎. Поигравшись с тегами смайликов в офисе, мы приняли сторону выражения. Как еще можно выразить # dealwithit😎?

Результат✔️

Вооружившись знаниями вариантов синтаксиса, символов селектора, вариантов тона кожи, решений моделирования и дурацкости UTF-16, мы можем написать сценарий, который генерирует правильные регулярные выражения на всех платформах. В конце концов, Instagram использует такие регулярные выражения, как:

Python 2.7

u"(?<!&)#(\w|(?:[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u2388\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692-\u2694\u2696\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD79\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED0\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3]|\uD83E[\uDD10-\uDD18\uDD80-\uDD84\uDDC0]|(?:0\u20E3|1\u20E3|2\u20E3|3\u20E3|4\u20E3|5\u20E3|6\u20E3|7\u20E3|8\u20E3|9\u20E3|#\u20E3|\\*\u20E3|\uD83C(?:\uDDE6\uD83C(?:\uDDEB|\uDDFD|\uDDF1|\uDDF8|\uDDE9|\uDDF4|\uDDEE|\uDDF6|\uDDEC|\uDDF7|\uDDF2|\uDDFC|\uDDE8|\uDDFA|\uDDF9|\uDDFF|\uDDEA)|\uDDE7\uD83C(?:\uDDF8|\uDDED|\uDDE9|\uDDE7|\uDDFE|\uDDEA|\uDDFF|\uDDEF|\uDDF2|\uDDF9|\uDDF4|\uDDE6|\uDDFC|\uDDFB|\uDDF7|\uDDF3|\uDDEC|\uDDEB|\uDDEE|\uDDF6|\uDDF1)|\uDDE8\uD83C(?:\uDDF2|\uDDE6|\uDDFB|\uDDEB|\uDDF1|\uDDF3|\uDDFD|\uDDF5|\uDDE8|\uDDF4|\uDDEC|\uDDE9|\uDDF0|\uDDF7|\uDDEE|\uDDFA|\uDDFC|\uDDFE|\uDDFF|\uDDED)|\uDDE9\uD83C(?:\uDDFF|\uDDF0|\uDDEC|\uDDEF|\uDDF2|\uDDF4|\uDDEA)|\uDDEA\uD83C(?:\uDDE6|\uDDE8|\uDDEC|\uDDF7|\uDDEA|\uDDF9|\uDDFA|\uDDF8|\uDDED)|\uDDEB\uD83C(?:\uDDF0|\uDDF4|\uDDEF|\uDDEE|\uDDF7|\uDDF2)|\uDDEC\uD83C(?:\uDDF6|\uDDEB|\uDDE6|\uDDF2|\uDDEA|\uDDED|\uDDEE|\uDDF7|\uDDF1|\uDDE9|\uDDF5|\uDDFA|\uDDF9|\uDDEC|\uDDF3|\uDDFC|\uDDFE|\uDDF8|\uDDE7)|\uDDED\uD83C(?:\uDDF7|\uDDF9|\uDDF2|\uDDF3|\uDDF0|\uDDFA)|\uDDEE\uD83C(?:\uDDF4|\uDDE8|\uDDF8|\uDDF3|\uDDE9|\uDDF7|\uDDF6|\uDDEA|\uDDF2|\uDDF1|\uDDF9)|\uDDEF\uD83C(?:\uDDF2|\uDDF5|\uDDEA|\uDDF4)|\uDDF0\uD83C(?:\uDDED|\uDDFE|\uDDF2|\uDDFF|\uDDEA|\uDDEE|\uDDFC|\uDDEC|\uDDF5|\uDDF7|\uDDF3)|\uDDF1\uD83C(?:\uDDE6|\uDDFB|\uDDE7|\uDDF8|\uDDF7|\uDDFE|\uDDEE|\uDDF9|\uDDFA|\uDDF0|\uDDE8)|\uDDF2\uD83C(?:\uDDF4|\uDDF0|\uDDEC|\uDDFC|\uDDFE|\uDDFB|\uDDF1|\uDDF9|\uDDED|\uDDF6|\uDDF7|\uDDFA|\uDDFD|\uDDE9|\uDDE8|\uDDF3|\uDDEA|\uDDF8|\uDDE6|\uDDFF|\uDDF2|\uDDF5|\uDDEB)|\uDDF3\uD83C(?:\uDDE6|\uDDF7|\uDDF5|\uDDF1|\uDDE8|\uDDFF|\uDDEE|\uDDEA|\uDDEC|\uDDFA|\uDDEB|\uDDF4)|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C(?:\uDDEB|\uDDF0|\uDDFC|\uDDF8|\uDDE6|\uDDEC|\uDDFE|\uDDEA|\uDDED|\uDDF3|\uDDF1|\uDDF9|\uDDF7|\uDDF2)|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C(?:\uDDEA|\uDDF4|\uDDFA|\uDDFC|\uDDF8)|\uDDF8\uD83C(?:\uDDFB|\uDDF2|\uDDF9|\uDDE6|\uDDF3|\uDDE8|\uDDF1|\uDDEC|\uDDFD|\uDDF0|\uDDEE|\uDDE7|\uDDF4|\uDDF8|\uDDED|\uDDE9|\uDDF7|\uDDEF|\uDDFF|\uDDEA|\uDDFE)|\uDDF9\uD83C(?:\uDDE9|\uDDEB|\uDDFC|\uDDEF|\uDDFF|\uDDED|\uDDF1|\uDDEC|\uDDF0|\uDDF4|\uDDF9|\uDDE6|\uDDF3|\uDDF7|\uDDF2|\uDDE8|\uDDFB)|\uDDFA\uD83C(?:\uDDEC|\uDDE6|\uDDF8|\uDDFE|\uDDF2|\uDDFF)|\uDDFB\uD83C(?:\uDDEC|\uDDE8|\uDDEE|\uDDFA|\uDDE6|\uDDEA|\uDDF3)|\uDDFC\uD83C(?:\uDDF8|\uDDEB)|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C(?:\uDDF9|\uDDEA)|\uDDFF\uD83C(?:\uDDE6|\uDDF2|\uDDFC))))[\ufe00-\ufe0f\u200d]?)+

Java 7+

"(?<!&)#(\w|[\\x{2712}\\x{2714}\\x{2716}\\x{271d}\\x{2721}\\x{2728}\\x{2733}\\x{2734}\\x{2744}\\x{2747}\\x{274c}\\x{274e}\\x{2753}-\\x{2755}\\x{2757}\\x{2763}\\x{2764}\\x{2795}-\\x{2797}\\x{27a1}\\x{27b0}\\x{27bf}\\x{2934}\\x{2935}\\x{2b05}-\\x{2b07}\\x{2b1b}\\x{2b1c}\\x{2b50}\\x{2b55}\\x{3030}\\x{303d}\\x{1f004}\\x{1f0cf}\\x{1f170}\\x{1f171}\\x{1f17e}\\x{1f17f}\\x{1f18e}\\x{1f191}-\\x{1f19a}\\x{1f201}\\x{1f202}\\x{1f21a}\\x{1f22f}\\x{1f232}-\\x{1f23a}\\x{1f250}\\x{1f251}\\x{1f300}-\\x{1f321}\\x{1f324}-\\x{1f393}\\x{1f396}\\x{1f397}\\x{1f399}-\\x{1f39b}\\x{1f39e}-\\x{1f3f0}\\x{1f3f3}-\\x{1f3f5}\\x{1f3f7}-\\x{1f4fd}\\x{1f4ff}-\\x{1f53d}\\x{1f549}-\\x{1f54e}\\x{1f550}-\\x{1f567}\\x{1f56f}\\x{1f570}\\x{1f573}-\\x{1f579}\\x{1f587}\\x{1f58a}-\\x{1f58d}\\x{1f590}\\x{1f595}\\x{1f596}\\x{1f5a5}\\x{1f5a8}\\x{1f5b1}\\x{1f5b2}\\x{1f5bc}\\x{1f5c2}-\\x{1f5c4}\\x{1f5d1}-\\x{1f5d3}\\x{1f5dc}-\\x{1f5de}\\x{1f5e1}\\x{1f5e3}\\x{1f5ef}\\x{1f5f3}\\x{1f5fa}-\\x{1f64f}\\x{1f680}-\\x{1f6c5}\\x{1f6cb}-\\x{1f6d0}\\x{1f6e0}-\\x{1f6e5}\\x{1f6e9}\\x{1f6eb}\\x{1f6ec}\\x{1f6f0}\\x{1f6f3}\\x{1f910}-\\x{1f918}\\x{1f980}-\\x{1f984}\\x{1f9c0}\\x{3297}\\x{3299}\\x{a9}\\x{ae}\\x{203c}\\x{2049}\\x{2122}\\x{2139}\\x{2194}-\\x{2199}\\x{21a9}\\x{21aa}\\x{231a}\\x{231b}\\x{2328}\\x{2388}\\x{23cf}\\x{23e9}-\\x{23f3}\\x{23f8}-\\x{23fa}\\x{24c2}\\x{25aa}\\x{25ab}\\x{25b6}\\x{25c0}\\x{25fb}-\\x{25fe}\\x{2600}-\\x{2604}\\x{260e}\\x{2611}\\x{2614}\\x{2615}\\x{2618}\\x{261d}\\x{2620}\\x{2622}\\x{2623}\\x{2626}\\x{262a}\\x{262e}\\x{262f}\\x{2638}-\\x{263a}\\x{2648}-\\x{2653}\\x{2660}\\x{2663}\\x{2665}\\x{2666}\\x{2668}\\x{267b}\\x{267f}\\x{2692}-\\x{2694}\\x{2696}\\x{2697}\\x{2699}\\x{269b}\\x{269c}\\x{26a0}\\x{26a1}\\x{26aa}\\x{26ab}\\x{26b0}\\x{26b1}\\x{26bd}\\x{26be}\\x{26c4}\\x{26c5}\\x{26c8}\\x{26ce}\\x{26cf}\\x{26d1}\\x{26d3}\\x{26d4}\\x{26e9}\\x{26ea}\\x{26f0}-\\x{26f5}\\x{26f7}-\\x{26fa}\\x{26fd}\\x{2702}\\x{2705}\\x{2708}-\\x{270d}\\x{270f}]|\\x{23}\\x{20e3}|\\x{2a}\\x{20e3}|\\x{30}\\x{20e3}|\\x{31}\\x{20e3}|\\x{32}\\x{20e3}|\\x{33}\\x{20e3}|\\x{34}\\x{20e3}|\\x{35}\\x{20e3}|\\x{36}\\x{20e3}|\\x{37}\\x{20e3}|\\x{38}\\x{20e3}|\\x{39}\\x{20e3}|\\x{1f1e6}[\\x{1f1e8}-\\x{1f1ec}\\x{1f1ee}\\x{1f1f1}\\x{1f1f2}\\x{1f1f4}\\x{1f1f6}-\\x{1f1fa}\\x{1f1fc}\\x{1f1fd}\\x{1f1ff}]|\\x{1f1e7}[\\x{1f1e6}\\x{1f1e7}\\x{1f1e9}-\\x{1f1ef}\\x{1f1f1}-\\x{1f1f4}\\x{1f1f6}-\\x{1f1f9}\\x{1f1fb}\\x{1f1fc}\\x{1f1fe}\\x{1f1ff}]|\\x{1f1e8}[\\x{1f1e6}\\x{1f1e8}\\x{1f1e9}\\x{1f1eb}-\\x{1f1ee}\\x{1f1f0}-\\x{1f1f5}\\x{1f1f7}\\x{1f1fa}-\\x{1f1ff}]|\\x{1f1e9}[\\x{1f1ea}\\x{1f1ec}\\x{1f1ef}\\x{1f1f0}\\x{1f1f2}\\x{1f1f4}\\x{1f1ff}]|\\x{1f1ea}[\\x{1f1e6}\\x{1f1e8}\\x{1f1ea}\\x{1f1ec}\\x{1f1ed}\\x{1f1f7}-\\x{1f1fa}]|\\x{1f1eb}[\\x{1f1ee}-\\x{1f1f0}\\x{1f1f2}\\x{1f1f4}\\x{1f1f7}]|\\x{1f1ec}[\\x{1f1e6}\\x{1f1e7}\\x{1f1e9}-\\x{1f1ee}\\x{1f1f1}-\\x{1f1f3}\\x{1f1f5}-\\x{1f1fa}\\x{1f1fc}\\x{1f1fe}]|\\x{1f1ed}[\\x{1f1f0}\\x{1f1f2}\\x{1f1f3}\\x{1f1f7}\\x{1f1f9}\\x{1f1fa}]|\\x{1f1ee}[\\x{1f1e8}-\\x{1f1ea}\\x{1f1f1}-\\x{1f1f4}\\x{1f1f6}-\\x{1f1f9}]|\\x{1f1ef}[\\x{1f1ea}\\x{1f1f2}\\x{1f1f4}\\x{1f1f5}]|\\x{1f1f0}[\\x{1f1ea}\\x{1f1ec}-\\x{1f1ee}\\x{1f1f2}\\x{1f1f3}\\x{1f1f5}\\x{1f1f7}\\x{1f1fc}\\x{1f1fe}\\x{1f1ff}]|\\x{1f1f1}[\\x{1f1e6}-\\x{1f1e8}\\x{1f1ee}\\x{1f1f0}\\x{1f1f7}-\\x{1f1fb}\\x{1f1fe}]|\\x{1f1f2}[\\x{1f1e6}\\x{1f1e8}-\\x{1f1ed}\\x{1f1f0}-\\x{1f1ff}]|\\x{1f1f3}[\\x{1f1e6}\\x{1f1e8}\\x{1f1ea}-\\x{1f1ec}\\x{1f1ee}\\x{1f1f1}\\x{1f1f4}\\x{1f1f5}\\x{1f1f7}\\x{1f1fa}\\x{1f1ff}]|\\x{1f1f4}\\x{1f1f2}|\\x{1f1f5}[\\x{1f1e6}\\x{1f1ea}-\\x{1f1ed}\\x{1f1f0}-\\x{1f1f3}\\x{1f1f7}-\\x{1f1f9}\\x{1f1fc}\\x{1f1fe}]|\\x{1f1f6}\\x{1f1e6}|\\x{1f1f7}[\\x{1f1ea}\\x{1f1f4}\\x{1f1f8}\\x{1f1fa}\\x{1f1fc}]|\\x{1f1f8}[\\x{1f1e6}-\\x{1f1ea}\\x{1f1ec}-\\x{1f1f4}\\x{1f1f7}-\\x{1f1f9}\\x{1f1fb}\\x{1f1fd}-\\x{1f1ff}]|\\x{1f1f9}[\\x{1f1e6}\\x{1f1e8}\\x{1f1e9}\\x{1f1eb}-\\x{1f1ed}\\x{1f1ef}-\\x{1f1f4}\\x{1f1f7}\\x{1f1f9}\\x{1f1fb}\\x{1f1fc}\\x{1f1ff}]|\\x{1f1fa}[\\x{1f1e6}\\x{1f1ec}\\x{1f1f2}\\x{1f1f8}\\x{1f1fe}\\x{1f1ff}]|\\x{1f1fb}[\\x{1f1e6}\\x{1f1e8}\\x{1f1ea}\\x{1f1ec}\\x{1f1ee}\\x{1f1f3}\\x{1f1fa}]|\\x{1f1fc}[\\x{1f1eb}\\x{1f1f8}]|\\x{1f1fd}\\x{1f1f0}|\\x{1f1fe}[\\x{1f1ea}\\x{1f1f9}]|\\x{1f1ff}[\\x{1f1e6}\\x{1f1f2}\\x{1f1fc}])+"

Цель-C

"[\U00002712\U00002714\U00002716\U0000271d\U00002721\U00002728\U00002733\U00002734\U00002744\U00002747\U0000274c\U0000274e\U00002753-\U00002755\U00002757\U00002763\U00002764\U00002795-\U00002797\U000027a1\U000027b0\U000027bf\U00002934\U00002935\U00002b05-\U00002b07\U00002b1b\U00002b1c\U00002b50\U00002b55\U00003030\U0000303d\U0001f004\U0001f0cf\U0001f170\U0001f171\U0001f17e\U0001f17f\U0001f18e\U0001f191-\U0001f19a\U0001f201\U0001f202\U0001f21a\U0001f22f\U0001f232-\U0001f23a\U0001f250\U0001f251\U0001f300-\U0001f321\U0001f324-\U0001f393\U0001f396\U0001f397\U0001f399-\U0001f39b\U0001f39e-\U0001f3f0\U0001f3f3-\U0001f3f5\U0001f3f7-\U0001f4fd\U0001f4ff-\U0001f53d\U0001f549-\U0001f54e\U0001f550-\U0001f567\U0001f56f\U0001f570\U0001f573-\U0001f579\U0001f587\U0001f58a-\U0001f58d\U0001f590\U0001f595\U0001f596\U0001f5a5\U0001f5a8\U0001f5b1\U0001f5b2\U0001f5bc\U0001f5c2-\U0001f5c4\U0001f5d1-\U0001f5d3\U0001f5dc-\U0001f5de\U0001f5e1\U0001f5e3\U0001f5ef\U0001f5f3\U0001f5fa-\U0001f64f\U0001f680-\U0001f6c5\U0001f6cb-\U0001f6d0\U0001f6e0-\U0001f6e5\U0001f6e9\U0001f6eb\U0001f6ec\U0001f6f0\U0001f6f3\U0001f910-\U0001f918\U0001f980-\U0001f984\U0001f9c0\U00003297\U00003299\U000000a9\U000000ae\U0000203c\U00002049\U00002122\U00002139\U00002194-\U00002199\U000021a9\U000021aa\U0000231a\U0000231b\U00002328\U00002388\U000023cf\U000023e9-\U000023f3\U000023f8-\U000023fa\U000024c2\U000025aa\U000025ab\U000025b6\U000025c0\U000025fb-\U000025fe\U00002600-\U00002604\U0000260e\U00002611\U00002614\U00002615\U00002618\U0000261d\U00002620\U00002622\U00002623\U00002626\U0000262a\U0000262e\U0000262f\U00002638-\U0000263a\U00002648-\U00002653\U00002660\U00002663\U00002665\U00002666\U00002668\U0000267b\U0000267f\U00002692-\U00002694\U00002696\U00002697\U00002699\U0000269b\U0000269c\U000026a0\U000026a1\U000026aa\U000026ab\U000026b0\U000026b1\U000026bd\U000026be\U000026c4\U000026c5\U000026c8\U000026ce\U000026cf\U000026d1\U000026d3\U000026d4\U000026e9\U000026ea\U000026f0-\U000026f5\U000026f7-\U000026fa\U000026fd\U00002702\U00002705\U00002708-\U0000270d\U0000270f]|[#]\U000020e3|[*]\U000020e3|[0]\U000020e3|[1]\U000020e3|[2]\U000020e3|[3]\U000020e3|[4]\U000020e3|[5]\U000020e3|[6]\U000020e3|[7]\U000020e3|[8]\U000020e3|[9]\U000020e3|\U0001f1e6[\U0001f1e8-\U0001f1ec\U0001f1ee\U0001f1f1\U0001f1f2\U0001f1f4\U0001f1f6-\U0001f1fa\U0001f1fc\U0001f1fd\U0001f1ff]|\U0001f1e7[\U0001f1e6\U0001f1e7\U0001f1e9-\U0001f1ef\U0001f1f1-\U0001f1f4\U0001f1f6-\U0001f1f9\U0001f1fb\U0001f1fc\U0001f1fe\U0001f1ff]|\U0001f1e8[\U0001f1e6\U0001f1e8\U0001f1e9\U0001f1eb-\U0001f1ee\U0001f1f0-\U0001f1f5\U0001f1f7\U0001f1fa-\U0001f1ff]|\U0001f1e9[\U0001f1ea\U0001f1ec\U0001f1ef\U0001f1f0\U0001f1f2\U0001f1f4\U0001f1ff]|\U0001f1ea[\U0001f1e6\U0001f1e8\U0001f1ea\U0001f1ec\U0001f1ed\U0001f1f7-\U0001f1fa]|\U0001f1eb[\U0001f1ee-\U0001f1f0\U0001f1f2\U0001f1f4\U0001f1f7]|\U0001f1ec[\U0001f1e6\U0001f1e7\U0001f1e9-\U0001f1ee\U0001f1f1-\U0001f1f3\U0001f1f5-\U0001f1fa\U0001f1fc\U0001f1fe]|\U0001f1ed[\U0001f1f0\U0001f1f2\U0001f1f3\U0001f1f7\U0001f1f9\U0001f1fa]|\U0001f1ee[\U0001f1e8-\U0001f1ea\U0001f1f1-\U0001f1f4\U0001f1f6-\U0001f1f9]|\U0001f1ef[\U0001f1ea\U0001f1f2\U0001f1f4\U0001f1f5]|\U0001f1f0[\U0001f1ea\U0001f1ec-\U0001f1ee\U0001f1f2\U0001f1f3\U0001f1f5\U0001f1f7\U0001f1fc\U0001f1fe\U0001f1ff]|\U0001f1f1[\U0001f1e6-\U0001f1e8\U0001f1ee\U0001f1f0\U0001f1f7-\U0001f1fb\U0001f1fe]|\U0001f1f2[\U0001f1e6\U0001f1e8-\U0001f1ed\U0001f1f0-\U0001f1ff]|\U0001f1f3[\U0001f1e6\U0001f1e8\U0001f1ea-\U0001f1ec\U0001f1ee\U0001f1f1\U0001f1f4\U0001f1f5\U0001f1f7\U0001f1fa\U0001f1ff]|\U0001f1f4\U0001f1f2|\U0001f1f5[\U0001f1e6\U0001f1ea-\U0001f1ed\U0001f1f0-\U0001f1f3\U0001f1f7-\U0001f1f9\U0001f1fc\U0001f1fe]|\U0001f1f6\U0001f1e6|\U0001f1f7[\U0001f1ea\U0001f1f4\U0001f1f8\U0001f1fa\U0001f1fc]|\U0001f1f8[\U0001f1e6-\U0001f1ea\U0001f1ec-\U0001f1f4\U0001f1f7-\U0001f1f9\U0001f1fb\U0001f1fd-\U0001f1ff]|\U0001f1f9[\U0001f1e6\U0001f1e8\U0001f1e9\U0001f1eb-\U0001f1ed\U0001f1ef-\U0001f1f4\U0001f1f7\U0001f1f9\U0001f1fb\U0001f1fc\U0001f1ff]|\U0001f1fa[\U0001f1e6\U0001f1ec\U0001f1f2\U0001f1f8\U0001f1fe\U0001f1ff]|\U0001f1fb[\U0001f1e6\U0001f1e8\U0001f1ea\U0001f1ec\U0001f1ee\U0001f1f3\U0001f1fa]|\U0001f1fc[\U0001f1eb\U0001f1f8]|\U0001f1fd\U0001f1f0|\U0001f1fe[\U0001f1ea\U0001f1f9]|\U0001f1ff[\U0001f1e6\U0001f1f2\U0001f1fc]"

Прощай

Если вы посмотрите на три случайных комментария в Instagram, скорее всего, вы найдете смайлики. Их использование распространилось на человеческие языки, и смайлики часто используются как заменители слов. Они являются естественным выбором для поддержки в хэштегах Instagram, но идентификация символов может быть затруднена на разных языках программирования. Только после анализа стандарта, нахождения вариаций символов и понимания языковых различий они становятся возможными для поддержки.

Увидимся в # ☁️

Томас Димсон - инженер-программист в группе данных Instagram, а также создал приложение Hyperlapse для Instagram.

Первоначально опубликовано на instagram-engineering.tumblr.com.