关于emoji,Go语言可以这么操作

Go语言精选

共 4847字,需浏览 10分钟

 ·

2021-03-18 22:17

点击上方蓝色“Go语言中文网”关注,每天一起学 Go

什么是emoji

emoji就是一些意形符号。

emoji的实现

首先,你必须能够区分unicodeutf8字符之间的区别:

  • unicode,字符集,就是一个表格,记录这字符和码点(通常表示为U+0031)之间的关系
  • utf8,是unicode的编码方案之一(还有utf16、utf32等)
  • 字符,是人类可以阅读的符号。emoji就是一批比较特殊的符号(可以理解为图片或者像素点集合)

因为是一种实现,所以不同平台实现的各不一样。以ok表情为例,各平台的实现如下:

image-20210302223155359

emoji分类

参考:https://www.unicode.org/Public/emoji/13.1/emoji-sequences.txt

Basic_Emoji

基本emoji,包含两种类型

  • 单一unicode字符
  • 单一unicode字符后面增加*U+FE0E*或者U+FE0F分别表示以黑白文本模式还是彩色模式展示表情

详情:https://www.unicode.org/Public/emoji/5.0/emoji-variation-sequences.txt

Emoji_Keycap_Sequence

键帽序列,都是0-9、#、*开头,然后后面紧跟着U+FE0FU+20E3两个字符组合而成。

字符长度:均是3字符

键帽序列:https://www.notion.so/80b0da16e0304d7ea7653e7f3fff47c8

需要注意的是苹果输入法打出的键帽序列是反的,即U+20E3在前U+FE0F在后面

func TestEmoji(t *testing.T)  {
 s := "1⃣️"
 fmt.Printf("字节数:%d, 字符数:%d\n"len(s), len([]rune(s)))
 hexDump(s)
}

func hexDump(s string)  {
 fmt.Printf("字符串:%s\n======================\n", s)
 for index, item := range []rune(s) {
  hex := strconv.FormatInt(int64(item), 16)
  fmt.Printf("序号%d:Unicode 码点:U+%s,字节数:%d\n", index, hex, utf8.RuneLen(item))
 }
}

// 字节数:7, 字符数:3
// 字符串:1⃣️
// ======================
// 序号0:Unicode 码点:U+31,字节数:1
// 序号1:Unicode 码点:U+20e3,字节数:3
// 序号2:Unicode 码点:U+fe0f,字节数:3

RGI_Emoji_Flag_Sequence

RGI(Recommended for General Interchange)表示可以在日常的交流中使用。

国家或地区缩写字母编码表:https://www.notion.so/ea3653771b2f42a98c7a6d23a44aa94f

如上表所示,U+1F1E6 ~ U+1F1FF,分表代表A ~ Z共计26个字符。

  • 比如中国缩写是CN,所以对应的旗帜编码就是U+1F1E8(C) U+1F1F3(N)
  • 比如美国缩写是US,所以对应的旗帜编码就是U+1F1FA(U) U+1F1F8(S)

RGI_Emoji_Tag_Sequence

这里有三个比较特殊的地区,分别是:英格兰苏格兰威尔士

英格兰(󠁧󠁢󠁥󠁮󠁧🏴󠁧󠁢󠁥󠁮󠁧󠁿):U+1F3F4 U+E0067 U+E0062 U+E0065 U+E006E U+E0067 U+E007F

苏格兰(🏴󠁧󠁢󠁳󠁣󠁴󠁿):U+1F3F4 U+E0067 U+E0062 U+E0073 U+E0063 U+E0074 U+E007F

威尔士(🏴󠁧󠁢󠁷󠁬󠁳󠁿):U+1F3F4 U+E0067 U+E0062 U+E0077 U+E006C U+E0073 U+E007F

他们是英国的组成国,具体请参考:https://v.qq.com/x/page/q0313hm0d0t.html?winzoom=1

RGI_Emoji_Modifier_Sequence

Unicode定义了5个用于emoji的肤色修饰字符,即特定的表情加上肤色修饰字符就会展示不同的颜色:

  • U+1F3FB:light skin tone
  • U+1F3FC:medium-light skin tone
  • U+1F3FD:medium skin tone
  • U+1F3FE:medium-dark skin tone
  • U+1F3FF:dark skin tone

比如👌的表情其实有5种肤色:

i

OK表情的5种肤色:https://www.notion.so/f557e5814e144e318b65251989d3afa6

零宽度链接符

ZWJ:https://www.unicode.org/Public/emoji/13.1/emoji-zwj-sequences.txt ,即Zero Width Joiner,也就是零宽度链接符号。ZWJ的unicode代码为U+200D,因为是没有宽度的链接符,所以不可见,他的作用就是链接两个字符,比如“👨‍👩‍👧‍👦”就是由U+200D链接四个字符而成:

ZWJ示例:https://www.notion.so/2f8c4a839edd4abb8148baa90c174419

字符串:👨‍👩‍👧‍👦,占用字节数:25, 字符数:7
======================
序号0:Unicode 码点:U+1f468,字节数:4
序号1:Unicode 码点:U+200d,字节数:3
序号2:Unicode 码点:U+1f469,字节数:4
序号3:Unicode 码点:U+200d,字节数:3
序号4:Unicode 码点:U+1f467,字节数:4
序号5:Unicode 码点:U+200d,字节数:3
序号6:Unicode 码点:U+1f466,字节数:4

当然这样的组合并不是无限的,所有合法的组合都可以在这里:https://www.unicode.org/Public/emoji/13.1/emoji-zwj-sequences.txt 找到。

emoji总结

  • emoji字符非固定长度,单个字符占用3-4个字符,所以判断是否是emoji表情,不能简单通过长度判断。

emoji长度不定:https://www.notion.so/d3090074f5444561b6e418b1967c96a3

  • emoji符号可以由一个或者多个字符组合而成,比如👨‍👩‍👧‍👦是由7个字符组成,共占用25个字节。

go与emoji

https://github.com/go-xman/go.emoji

原理就是根据emoji两个官方文档 Emoji Sequence:https://www.unicode.org/Public/emoji/13.1/emoji-sequences.tx 和 Emoji ZWJ Sequence:https://www.unicode.org/Public/emoji/13.1/emoji-zwj-sequences.txt ,官方已经将可以组合的emoji表情一一列举出来了。

代码实现就是将所有合法的序列全部导出成为一棵树。当检查字符串子串的时候,匹配树中所代表的合法的子串就可以了。

func TestEmoji(t *testing.T)  {
 s := "👩‍👩‍👦🇨🇳"
 _ = emoji.ReplaceAllEmojiFunc(s, func(emoji string) string {
  hexDump(emoji)
  return ""
 })
}

func hexDump(s string)  {
 fmt.Printf("字符串:%s,占用字节数:%d, 字符数:%d\n======================\n", s, len(s), len([]rune(s)))
 for index, item := range []rune(s) {
  hex := strconv.FormatInt(int64(item), 16)
  fmt.Printf("序号%d:Unicode 码点:U+%s,字节数:%d\n", index, hex, utf8.RuneLen(item))
 }
}

=== RUN   TestEmoji
字符串:👩‍👩‍👦,占用字节数:18, 字符数:5
======================
序号0:Unicode 码点:U+1f469,字节数:4
序号1:Unicode 码点:U+200d,字节数:3
序号2:Unicode 码点:U+1f469,字节数:4
序号3:Unicode 码点:U+200d,字节数:3
序号4:Unicode 码点:U+1f466,字节数:4
字符串:🇨🇳,占用字节数:8, 字符数:2
======================
序号0:Unicode 码点:U+1f1e8,字节数:4
序号1:Unicode 码点:U+1f1f3,字节数:4
--- PASS: TestEmoji (0.00s)
PASS

参考文献

  • Unicode:https://zh.wikipedia.org/wiki/Unicode
  • Unicode 颜文字(emoji)格式和 Go 代码处理:https://segmentfault.com/a/1190000022100299
  • About Emoji:https://home.unicode.org/emoji/about-emoji/
  • 繪文字:https://zh.wikipedia.org/wiki/%E7%B9%AA%E6%96%87%E5%AD%97

本文作者首发于 Go语言中文网网站,转载请联系授权





推荐阅读


福利

我为大家整理了一份从入门到进阶的Go学习资料礼包,包含学习建议:入门看什么,进阶看什么。关注公众号 「polarisxu」,回复 ebook 获取;还可以回复「进群」,和数万 Gopher 交流学习。

浏览 45
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报