PHP: Как сопоставить ряд парных суррогатных смайликов/смайликов Unicode?

Ответ anubhava о сопоставлении диапазонов символов Юникода привел меня к регулярному выражению для очистки до определенного диапазона одиночных кодовых точек символов. Теперь я могу сопоставлять все разные символы в этом списке (включая смайлики) с помощью этого простого выражения:

preg_replace('/[\x{2600}-\x{26FF}]/u', '', $str);

Однако я также хочу сопоставить те, что указаны в этом списке парных/двойных суррогатов. emoji, но как nhahtdh объясняется в комментарий:

Существует диапазон от d800 до dfff для указания суррогатов в UTF-16, чтобы можно было указать больше символов. Один суррогат не является допустимым символом в UTF-16 (необходима пара, чтобы указать допустимый символ).

Так, например, когда я пытаюсь это:

preg_replace('/\x{D83D}\x{DE00}/u', '', $str);

Для замены только первого из парных заменителей в этом списке , то есть: ????

PHP бросает это:

preg_replace(): Ошибка компиляции: недопустимая кодовая точка Unicode (>= 0xd800 && <= 0xdfff)

Я пробовал несколько разных комбинаций, включая предполагаемую комбинацию вышеуказанных кодовых точек в UTF8 для ???? ('/[\x{00F0}\x{009F}\x{0098}\x{0080}]/u'), но я так и не смог его сопоставить. Я также изучил другие модификаторы шаблонов PCRE, но, похоже, u — единственный, который позволяет указывать через UTF8.

Я пропустил здесь какую-либо альтернативу «побега»?


person CPHPython    schedule 21.08.2018    source источник
comment
Вы просто пытаетесь создать регулярное выражение для соответствия этим 80 смайликам и использовать его как жестко закодированный шаблон, или вы пытаетесь написать код, который преобразует U+1F600 в \x{D83D}\x{DE00}?   -  person Wiktor Stribiżew    schedule 21.08.2018
comment
Какая версия PHP?   -  person revo    schedule 21.08.2018
comment
@WiktorStribiżew и то, и другое, если возможно. Шаблон жестко заданный будет диапазоном.   -  person CPHPython    schedule 21.08.2018
comment
@revo PHP 7.1.5 и выше.   -  person CPHPython    schedule 21.08.2018
comment
Если ваш PHP не поставляется со сборкой PCRE для UTF-16, вы не можете выполнить такое сопоставление. Начиная с PHP 7.0, вы можете использовать кодовые точки Unicode, следуя этому синтаксису \u{XXXX}, например. preg_replace("~\u{1F600}~", '', $str); (обратите внимание на двойные кавычки)   -  person revo    schedule 21.08.2018
comment
@revo вау, совсем забыл об этом (некоторое время назад я читал новые функции)... Спасибо за это, я придумал это решение для объединения обоих типов диапазонов.   -  person CPHPython    schedule 21.08.2018


Ответы (1)


комментарий revo выше было очень полезно найти решение:

Если ваш PHP не поставляется со сборкой PCRE для UTF-16, вы не можете выполнить такое сопоставление. Начиная с PHP 7.0 вы можете использовать кодовые точки Unicode, следуя этому синтаксису \u{XXXX}, например. preg_replace("~\u{1F600}~", '', $str); (Обратите внимание на двойные кавычки)

Поскольку я использую PHP 7, echo "\u{1F602}"; выводит ???? в соответствии с этой страницей PHP RFC на побеге unicode. Суть этого предложения заключалась в следующем:

Добавлена ​​новая управляющая последовательность для строк в двойных кавычках и heredocs.

  • \u{ codepoint-digits }, где codepoint-digits состоит из шестнадцатеричных цифр.

Это означает, что совпадающая строка в preg_replace (обычно заключенная в одинарные кавычки, чтобы не путаться с раскрытием строковой переменной в двойных кавычках) теперь нуждается в некотором preg_quote магия. Это решение, которое я придумал:

preg_replace(
  // single point unicode list
  "/[\x{2600}-\x{26FF}".
  // http://www.fileformat.info/info/unicode/block/miscellaneous_symbols/list.htm
  // concatenates with paired surrogates
  preg_quote("\u{1F600}", '/')."-".preg_quote("\u{1F64F}", '/').
  // https://www.fileformat.info/info/unicode/block/emoticons/list.htm
  "]/u",
  '',
  $str
);

Вот доказательство вышеизложенного в 3v4l.

РЕДАКТИРОВАТЬ: более простое решение

В сделан еще один комментарий revo, кажется, что, помещая символы Юникода непосредственно в класс символов регулярного выражения, строки в одинарных кавычках и предыдущие версии PHP (например, 4.3.4) поддерживаются:

preg_replace('/[☀-⛿????-????]/u','YOINK',$str);

Однако для использования функции нового PHP 7 вам все равно нужно дважды цитаты:

preg_replace("/[\u{2600}-\u{26FF}\u{1F600}-\u{1F64F}]/u",'YOINK',$str);

Вот доказательство revo в 3v4l.

person CPHPython    schedule 21.08.2018
comment
Я хотел бы добавить, что вам не нужен ни preg_quote, ни синтаксис PCRE \x{XXXX}. Просто иди с /[\u{2600}-\u{26FF}\u{1F600}-\u{1F64F}]/u. Это равно /[☀-⛿????-????]/u. Посмотреть демо здесь 3v4l.org/uA3mD - person revo; 21.08.2018
comment
@revo ха-ха, это потрясающе! Непосредственное размещение символов допускает замену в PHP 4! Я думаю, это лучшее решение (если IDE не волнуется). Я отредактировал ответ с вашим открытием. Большое спасибо! - person CPHPython; 21.08.2018