如何使用PHP将32位(4字节)表情符号包装在任意字符串中?

How to wrap 32-bit (4 bytes) emojis in arbitrary string using PHP?

提问人:Marc T. 提问时间:8/22/2023 最后编辑:Marc T. 更新时间:8/24/2023 访问量:74

问:

我正在使用这个 PHP 函数将表情符号包装在任意 HTML 标签中,这允许我在网页上设置它们的样式,因为 CSS3 还不直接支持多字节字符的样式,至少我还没有找到任何用于此目的的 CSS 选择器:

function wrap_emojis($s, $str_before, $str_after) {
    $default_encoding = mb_regex_encoding();
    mb_regex_encoding('UTF-8');
    $s = mb_ereg_replace('([^\x{0000}-\x{FFFF}])', $str_before . '\\1' . $str_after, $s);
    mb_regex_encoding($default_encoding);
    return $s;
}

问题是它适用于较低范围的表情符号,例如 😎 (01F60E),但不适用于较高范围的表情符号,例如 ☀️ (2600FE0F)

任何想法如何修复PHP函数,使其也适用于4字节范围?

例如,如果我调用 wrap_emojis(“zzz zzz☀️”, “A”, “B”);预期结果:“zzzA☀️Bzzz”。实际结果:“zzz☀️zzz”。但它适用于问题中提到的较低范围的表情符号,例如 wrap_emojis(“zzz zzz😎”, “A”, “B”) 返回:“zzzA😎Bzzz”

php 则表达 UTF8MB4

评论

0赞 Tobias 8/22/2023
您能否给出一个带有参数的示例调用以及预期结果?wrap_emojis
0赞 Marc T. 8/22/2023
wrap_emojis(“XYZ XYZ☀️”, “A”, “B”);预期结果:“XYZA☀️BXYZ”。实际结果:“XYZ XYZ☀️”。但它适用于问题中提到的较低范围的表情符号。
0赞 KIKO Software 8/22/2023
这似乎有效:3v4l.org/gR5o1 注意输出右上角的小眼睛图标以查看处理后的 HTML。
1赞 Sammitch 8/23/2023
FWIW 这不是一个“高范围”的东西,这是一个 2 码点序列。它是一个 u2600 ☀ 和一个 uFE0F“变体选择器”,用于生成实际渲染的字形。
1赞 Sammitch 8/23/2023
尽管您可能不喜欢@bobblebubble链接的正则表达式,但这就是表情符号的现实。它是一个散布在Unicode中的大杂烩,是“Combining Mark Hell”的门户,每次Unicode联盟更新规范时,它只会变得更加复杂。

答:

0赞 Marc T. 8/23/2023 #1

好吧,这并不难,我只需要编写匹配 2 组 2 字节(带有“变体选择器”的 mb4)或(当找不到时)的正则表达式,然后是不在较低 2 字节范围内的任何字符。很确定它会导致外语问题,但在英语中,它效果很好!

$s = mb_ereg_replace('([\x{0100}-\x{FFFF}][\x{0000}-\x{FFFF}]|[^\x{0000}-\x{FFFF}])', $str_before . '\\1' . $str_after, $s);

希望它能启发其他人。干杯 🤣