PHP:如何匹配一系列 unicode 配对代理表情符号/表情符号?

Posted

技术标签:

【中文标题】PHP:如何匹配一系列 unicode 配对代理表情符号/表情符号?【英文标题】:PHP: How to match a range of unicode paired surrogates emoticons/emoji? 【发布时间】:2019-01-27 13:28:55 【问题描述】:

anubhava's answer about matching ranges of unicode characters 引导我使用正则表达式来清理特定范围的单个字符代码点。有了它,现在我可以用这个简单的表达式匹配所有miscellaneous symbols in this list(包括表情符号):

preg_replace('/[\x2600-\x26FF]/u', '', $str);

但是,我也想匹配这个list of paired/double surrogates emoji中的那些,但是作为nhahtdh explained in a comment:

d800dfff 的范围内可以指定UTF-16 中的代理项以允许指定更多字符。 单个代理不是 UTF-16 中的有效字符(需要一对来指定有效字符)。

所以,例如,当我尝试这个时:

preg_replace('/\xD83D\xDE00/u', '', $str);

仅替换paired surrogates on this list 中的第一个,即:????

php 抛出这个:

preg_replace():编译失败:不允许的 Unicode 代码点(>= 0xd800 && <= 0xdfff)

我尝试了几种不同的组合,包括UTF8 for ???? ('/[\x00F0\x009F\x0098\x0080]/u') 中上述代码点的假定组合,但我仍然无法匹配它。我还查看了其他PCRE pattern modifiers,但似乎u 是唯一允许指向UTF8 的。

我在这里错过了任何“逃避”的选择吗?

【问题讨论】:

您是否只是想构建一个正则表达式来匹配这 80 个表情符号并将其用作“硬编码”模式,或者您是否正在尝试编写将“转换”U+1F600\xD83D\xDE00 的代码? 哪个 PHP 版本? @WiktorStribiżew 如果可能的话。 hardcoded 模式将是一个范围。 @revo PHP 7.1.5 及以上版本。 如果您的 PHP 未附带针对 UTF-16 的 PCRE 构建,那么您将无法执行此类匹配。从 PHP 7.0 开始,您可以使用 Unicode 代码点,遵循此语法 \uXXXX,例如preg_replace("~\u1F600~", '', $str);(注意双引号) 【参考方案1】:

revo's comment above 对找到解决方案很有帮助:

如果您的 PHP 未附带针对 UTF-16 的 PCRE 构建,则您无法执行此类匹配。 从 PHP 7.0 开始,您可以使用 Unicode 代码点遵循此语法 \uXXXX 例如preg_replace("~\u1F600~", '', $str);(注意双引号

由于我使用的是 PHP 7,echo "\u1F602"; 输出?根据这个PHP RFC page on unicode escape。这个提议本质上是:

双引号字符串 和 heredocs 添加了新的转义序列。

\u codepoint-digits 其中codepoint-digits 由十六进制数字组成。

这意味着preg_replace 中的匹配字符串(通常是单引号以免与双引号字符串变量扩展混淆)现在需要一些preg_quote magic。这是我想出的解决方案:

preg_replace(
  // single point unicode list
  "/[\x2600-\x26FF".
  // http://www.fileformat.info/info/unicode/block/miscellaneous_symbols/list.htm
  // concatenates with paired surrogates
  preg_quote("\u1F600", '/')."-".preg_quote("\u1F64F", '/').
  // https://www.fileformat.info/info/unicode/block/emoticons/list.htm
  "]/u",
  '',
  $str
);

这是proof of the above in 3v4l。

编辑:更简单的解决方案

在another comment made by revo 中,似乎通过将 unicode 字符直接放入正则表达式字符类,支持单引号字符串和以前的 PHP 版本(例如 4.3.4):

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

对于使用PHP 7's new feature though,你仍然需要双引号:

preg_replace("/[\u2600-\u26FF\u1F600-\u1F64F]/u",'YOINK',$str);

这里是revo's proof in 3v4l。

【讨论】:

我想补充一点,您既不需要 preg_quote 也不需要 PCRE 的 \xXXXX 语法。只需使用/[\u2600-\u26FF\u1F600-\u1F64F]/u。这等于/[☀-⛿?-?]/u。在此处查看现场演示3v4l.org/uA3mD @revo 哈哈,这太棒了!直接放置字符允许在 PHP 4 中替换!我想这是最好的解决方案(如果 IDE 没有崩溃的话)。我用你的发现编辑了答案。非常感谢!

以上是关于PHP:如何匹配一系列 unicode 配对代理表情符号/表情符号?的主要内容,如果未能解决你的问题,请参考以下文章

两个EXCEL表格,怎么让数据配对,以型号作为关联

怎样根据姓名匹配对应数据,Excel如何从一个表中分类提取另一个表对应

按字典顺序选择团队配对及其相对表现之间的匹配

求助,SQlServer用外连接查询出未匹配的数据

[正则表达式]匹配Unicode

(二分图最大匹配)51NOD 2006 飞行员配对