前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go 统计含 emoji 字符串字符数

Go 统计含 emoji 字符串字符数

作者头像
恋喵大鲤鱼
发布2021-07-19 15:46:29
1.3K0
发布2021-07-19 15:46:29
举报
文章被收录于专栏:C/C++基础

1.背景

项目种需要统计用户昵称的字符数量进行限制,用户可以输入英文,中文,emoji 字符,当用户输入中英文和普通的 emoji 字符时,将字符串转为 []rune 进行统计没有问题。

代码语言:javascript
复制
func main() {
	s0 := "我爱中国"               // 中文
	s1 := "我爱China"              // 中英文
	s2 := "我爱China?"             // 中英文加普通 emoji(笑脸)
	fmt.Println(len([]rune(s0))) // 4
	// 或 fmt.Println(utf8.RuneCountInString(s0))
	fmt.Println(len([]rune(s1))) // 7
	// 或 fmt.Println(utf8.RuneCountInString(s1))
	fmt.Println(len([]rune(s2))) // 8
	// fmt.Println(utf8.RuneCountInString(s2))
}

但是,当字符串种含有旗帜类的 emoji 字符,比如下面的中国旗帜,使用 []rune 无法准确统计字符数量。

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
func main() {
	s := "我爱中国??"
	fmt.Println(len([]rune(s))) // 6
}

预期输出 5,结果输出了 6。

因为代码编辑器不支持旗帜 emoji,所以显示为 CN。

2.emoji 分类

你可能以为一个 emoji 字符仅用一个 Unicode 码值表示,虽然大部分 emoji 是这样的,但实际上并非如此。

上面统计包含旗帜 emoji 字符串时,错误地将一个 emoji 字符统计成了两个字符,原因也是如此。

emoji 实际上有多种分类:

Basic_Emoji Emoji_Keycap_Sequence RGI_Emoji_Flag_Sequence RGI_Emoji_Tag_Sequence RGI_Emoji_Modifier_Sequence RGI_Emoji_ZWJ_Sequence

2.1 Basic_Emoji

基本 emoji,对应 Emoji Sequences 标准书 Basic_Emoji 小节。

包含两种类型:

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

2.2 Emoji_Keycap_Sequence

键帽序列,对应 Emoji Sequences 标准书 Emoji_Keycap_Sequence 小节。

这一类序列总共有12组,这里其实就对应着电话上的12个按钮,分别是 0~9 十个字符,外加 # 和 * 开头,然后后面紧跟着 U+FE0F 和 U+20E3 两个字符组成。

字符长度:均是 Unicode 码值。

2.3 RGI_Emoji_Flag_Sequence

国家/地区旗帜序列。对应 Emoji Sequences 标准书 RGI_Emoji_Flag_Sequence 小节。

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

这一组文字均由两个 unicode 字符组成,字符的值为 U+1F1E6 到 U+1F1FF 的26个字符,一一对应着 A 到 Z。这一组 unicode 文字对应着使用两个字母的国家/地区码所对应的国家/地区旗帜,以及用 UN 表示的联合国旗和 EU 表示的欧盟旗。

合法的旗帜总共有 258 个组合,标准中完整地列出了。需要注意的是,U+1F1E6 到 U+1F1FF 这26个字符不能单独出现,它们是专门用于这一类旗帜所使用的特殊 unicode 字符。

国家/地区码可参见 ISO 3166-1

2.4 RGI_Emoji_Tag_Sequence

标记序列,对应 Emoji Sequences 标准书 RGI_Emoji_Tag_Sequence 小节。

这一组其实是 unicode 预留的扩展类别,虽然在 emoji 中定义了所谓 “tag latin letter” 用于此类别,但是目前只有三个合法 emoji,从展示效果上分别是 英格兰、苏格兰、威尔士旗帜。

英格兰(????????????):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

2.5 RGI_Emoji_Modifier_Sequence

修饰符序列,对应 Emoji Sequences 标准书 RGI_Emoji_Modifier_Sequence 小节。

Unicode 定义了五个用于 emoji 的肤色字符,分别是:U+1F3FB U+1F3FC U+1F3FD U+1F3FE U+1F3FF,在 unicode 标准中分别表示:

light skin tone medium-light skin tone medium skin tone medium-dark skin tone dark skin tone

用于与部分基本 emoji 经字符搭配,用于调整相应文字中的肤色。常用在需要西方式 “政治正确” 的场合。

这五个字符按照标准而言是不会单独出现的,必然是跟在一个基本 emoji 后面。

Unicode 总共定义了 580 个 modifier sequences,也就是说有 116 个基本 emoji 字符可以搭配肤色字符使用。

2.6 RGI_Emoji_ZWJ_Sequence

零宽度连接符,对应 Emoji ZWJ Sequences 标准书

ZWJ 即 Zero Width Joiner。ZWJ 的 unicode 码值为 U+200D,因为是没有宽度的连接符,所以不可见,它的作用就是连接两个字符,比如 “?‍?‍?‍?” 就是由 U+200D 连接四个 emoji 字符而成。

在这里插入图片描述
在这里插入图片描述

并不是所有的 emoji 都可以任意连接。Unicode 定义了 1122 个 Emoji ZWJ 序列类型的文字。在 Emoji ZWJ Sequences 标准书可以查阅完整列表。

3.正确统计字符串字符数量

几番搜索,终于发现开源包 uniseg 可以准确识别包含 emoji 字符的字符串的字符数量。它根据 Unicode Standard Annex #29中指定的规则来中断字符串。

使用示例:

代码语言:javascript
复制
package main

import (
    "fmt"

    "github.com/rivo/uniseg"
)

func main() {
    s := "我爱中国??"
	fmt.Println(uniseg.GraphemeClusterCount(s))
}

运行输出:

代码语言:javascript
复制
5

4.小结

不含 emoji 字符的字符串,可以使用标准库 utf8 包内的相关函数来统计字符串长度,比如 utf8.RuneCountInString(),或者将字符串转换为 []rune 在通过 len() 来获取长度。

因为 emoji 字符长度不固定,判断是否是 emoji 表情,不能简单按照 UTF8 编码规则来判断,而应该根据 Unicode 码值范围与连接顺序来判断是否为 emoji,可以使用开源库 uniseg 来准确获取包含 emoji 字符的字符串长度(字符数)。


本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/07/15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.背景
  • 2.emoji 分类
    • 2.1 Basic_Emoji
      • 2.2 Emoji_Keycap_Sequence
        • 2.3 RGI_Emoji_Flag_Sequence
          • 2.4 RGI_Emoji_Tag_Sequence
            • 2.5 RGI_Emoji_Modifier_Sequence
              • 2.6 RGI_Emoji_ZWJ_Sequence
              • 3.正确统计字符串字符数量
              • 4.小结
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档