最近接到一个将字符串中Emoji表情符号的转为十六进制UTF8编码的任务。花了几天挖呀挖,总算捣鼓明白了,写了一个函数来完成任务,现记录下来,分享给大家。
Oracle数据表中,字符串含有Emoji表情符号,有些平台从数据库导出时,能正确显示Emoji表情,如:
"👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦"
或:
<doc:Ustrd>👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦</doc:Ustrd>
而有些平台却将Emoji表情导出为乱码,如:
<doc:Ustrd>👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ðŸ‘¨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ðŸ‘¨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ðŸ‘¨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ðŸ‘¨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ðŸ‘¨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ðŸ‘¨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ðŸ‘¨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ðŸ‘¨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦</doc:Ustrd>
这种乱码,可能是对应平台字符集无法正确转换所造成。
我的任务是将这些字符串先做处理,将字符串中含有的Emoji表情转换为其对应的十六进制UTF8编码,再提供给其他平台使用。如:
'Happy Birthday!🎂Happy Birthday!😀'
要求转换为:
'Happy Birthday!\xF0\x9F\x8E\x82Happy Birthday!\xF0\x9F\x98\x80'
如果整个字符串都是Emoji 表情,可以使用dump()函数转化后稍加处理即可,如:
SELECT DUMP('👨👩👧👦🎂😀', 16) FROM DUAL;
->
Typ=96 Len=33: f0,9f,91,a8,e2,80,8d,f0,9f,91,a9,e2,80,8d,f0,9f,91,a7,e2,80,8d,f0,9f,91,a6,f0,9f,8e,82,f0,9f,98,80
-> \xF0\x9F\x91\xA8\xE2\x80\x8D\xF0\x9F\x91\xA9\xE2\x80\x8D\xF0\x9F\x91\xA7\xE2\x80\x8D\xF0\x9F\x91\xA6\xF0\x9F\x8E\x82\xF0\x9F\x98\x80
而实际情况是,Emoji表情与其他字符混杂多在一起,要求是:只转化Emoji表情符,其他字符保持不变。
所以,先从字符串中识别找出Emoji表情,然后再做转换!转换容易,识别可就难了!Emoji表情是个啥?一共有多少?怎么从字符串里识别?一堆疑问!好家伙,瞬间,难度拉满!
请教了几个同事,他们也没有碰到过该问题。于是花了几天在网上挖呀挖,不断的在Oracle中测试,上面的疑问总算一点点的明朗起来!
网络就是一个神奇的地方,原来早有人碰到过类似问题了,找到不少Java语言中,用正则表达式匹配Emoji表情的方法。
Emoji 的处理 - 使用正则表达式匹配所有 Emoji表情_emoji正则_liu__software的博客-CSDN博客
正则验证输入框禁止输入emoji表情_猿者上钩的博客-CSDN博客
虽然没有挖到现成的Oracle SQL或PL/SQL处理的方法,但受这些方法用正则表达式匹配emoji符号的启发,于是,赶紧弄个简单的Emoji表情,用正则表达式测探一下:
SELECT REGEXP_SUBSTR('Happy Birthday!☺', '[' || UNISTR('\263A') || ']') AS "Emoji" FROM DUAL;
不错,识别出来了,很是惊喜!感觉这条路是可行的。接下来就是要搞清楚怎么用Oracle的正则表达式匹配所有Emoji表情了。
首先,什么是Emoji表情?
原来Emoji表情有标准组织进行分类管理和进行统一的Unicode编码,在最新V15.0版本中数量已经达到了3000多个。参见:
https://www.unicode.org/emoji/charts/full-emoji-list.html#26f1
Emoji unicode characters for use on the web
https://www.unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt
所有Emoji表情的Unicode编码又分为两种(如下图),一种是4位十六进制编码,一种为5位十六进制编码。
然后,Oracle是用UNISTR()函数查看Unicode码对应的Emoji表情符号,这个函数有限制,只能查看4位十六进制编码,对于5位十六进制编码,他会解读为前4位 加 后1位(如下图)。
所以,网上列表中4位Unicode码的Emoji表情,是可以直接使用UNISTR()函数表示,而5位1Fxxx 打头Unicode码的Emoji表情,则需要弄明白如何使用UNISTR()函数来表示。
受上面方法中正则表达式写法的提醒,感觉这些5位Unicode码的Emoji表情,可能与这个表示 [\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF]有关。
探视了几次,果真如此,原来是用两个4位Unicode码来表示。如下:
SELECT '\D83C\DC00' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC00') AS "CHAR" FROM DUAL
继续探视一组16个:
SELECT '\D83C\DC00' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC00') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC01' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC01') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC02' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC02') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC03' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC03') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC04' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC04') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC05' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC05') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC06' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC06') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC07' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC07') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC08' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC08') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC09' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC09') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC0A' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC0A') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC0B' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC0B') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC0C' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC0C') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC0D' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC0D') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC0E' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC0E') AS "CHAR" FROM DUAL UNION ALL
SELECT '\D83C\DC0F' AS "UNICODE", UNISTR('\D83C') || UNISTR('\DC0F') AS "CHAR" FROM DUAL;
第5行的:'D83C\DC04',正是对应Unicode:1F004的Emoji表情“🀄”。
按这种方法不断探视,终于搞明白了这些5位码与2个4位码的对应关系,整理对应规则如下:
1F000 - 1F0FF | \D83C\DC00 - \D83C\DCFF |
1F100 - 1F1FF | \D83C\DD00 - \D83C\DDFF |
1F200 - 1F2FF | \D83C\DE00 - \D83C\DEFF |
1F300 - 1F3FF | \D83C\DF00 - \D83C\DFFF |
1F400 - 1F4FF | \D83D\DC00 - \D83D\DCFF |
1F500 - 1F5FF | \D83D\DD00 - \D83D\DDFF |
1F600 - 1F6FF | \D83D\DE00 - \D83D\DEFF |
1F700 - 1F7FF | \D83D\DF00 - \D83D\DFFF |
1F800 - 1F8FF | \D83E\DC00 - \D83E\DCFF |
1F900 - 1F9FF | \D83E\DD00 - \D83E\DDFF |
1FA00 - 1FAFF | \D83E\DE00 - \D83E\DEFF |
其中较为特殊国旗Emoji表情,是由2个字母表情符号组合而成。
单字母国旗符号A-Z(与常规字母A-Z编码不一样)对应范围如下:
1F1E6 - 1F1FF : \D83C\DDE6 - \D83C\DDFF
其次,怎么用正则表达式匹配所有Emoji表情?
继续挖!
非常感谢下面链接中这个祁同学的研究!这个研究,对于我来说就是巨人的肩膀!由此了解到了匹配Emoji表情的正则表达式总公式,想了解的可以直接去链接里学习,该同学也提供了PHP语言正则式匹配Emoji表情的方法。
我这里也直接引用。
Unicode官方网站中Emoji的文档中有关于Emoji的定义和正则表达式是这样的:
\p{RI} \p{RI}
| \p{Emoji}
( \p{EMod}
| \x{FE0F} \x{20E3}?
| [\x{E0020}-\x{E007E}]+ \x{E007F} )?
(\x{200D} \p{Emoji}
( \p{EMod}
| \x{FE0F} \x{20E3}?
| [\x{E0020}-\x{E007E}]+ \x{E007F} )?
)*
\p{RI} 地区指示符 1F1E6 - 1F1FF (🇦 regional indicator symbol letter a) (🇿 regional indicator symbol letter z)
\p{Emoji} Emoji字符 emoji-data.txt文件中emoji属性的1404个(14.0) Emoji字符
\p{EMod} Emoji修饰符 5种skin-tone:1F3FB - 1F3FF
\x{FE0F} Emoji变体符号
\x{20E3} 键帽符号
\x{E0020}-\x{E007E} 标签符号
\x{E007F} 结束标签符号
\x{200D} 零宽连接符
正则表达式的含义:国旗 1个 | (某种Emoji组合) 1个 (零宽连接 某种Emoji组合) 0-n个
“某种Emoji组合”的含义:Emoji字符 1个 (Emoji修饰符 1个| Emoji变体符号 1个 键帽符号 0-1个 | 标签符号 1-n个 结束标签符号 1个) 0-1个
上面这一段理论,将单Emoji表情和组合Emoji表情,用一个公式表示出来,对我本次用Oracle来实现,启发最大。
该公式分为2个部分:
1)国旗Emoji
2)单Emoji或Emoji组合
而我在Oracle中的实现时,稍作了变通,分为了三部分:
1)#*0-9,这12个特殊的按键组合Emoji
2)国旗Emoji
3)单Emoji或Emoji组合
实现代码如下:
SELECT REGEXP_SUBSTR('Happy Birthday!🇺🇸#⃣👩❤️💋👨😶🌫️Happy Birthday!😀',
'[#*0-9]' || UNISTR('\FE0F') || '?' || UNISTR('\20E3')
|| '|'
|| '[' || UNISTR('\D83C') || UNISTR('\DDE6') || '-' || UNISTR('\D83C') || UNISTR('\DDFF') || ']{2}'
|| '|'
|| '['
|| UNISTR('\D83C') || UNISTR('\DC00') || '-' || UNISTR('\D83C') || UNISTR('\DFFA')
|| '|' || UNISTR('\D83D') || UNISTR('\DC00') || '-' || UNISTR('\D83D') || UNISTR('\DFFF')
|| '|' || UNISTR('\D83E') || UNISTR('\DD0C') || '-' || UNISTR('\D83E') || UNISTR('\DEFF')
|| '|' || UNISTR('\00A9') || '|' || UNISTR('\00AE')
|| '|' || UNISTR('\203C') || '|' || UNISTR('\2049') || '|' || UNISTR('\2122') || '|' || UNISTR('\2139')
|| '|' || UNISTR('\2190') || '-' || UNISTR('\21AF')
|| '|' || UNISTR('\2310') || '-' || UNISTR('\231F')
|| '|' || UNISTR('\2326') || '-' || UNISTR('\232F')
|| '|' || UNISTR('\2380') || '-' || UNISTR('\238F')
|| '|' || UNISTR('\23C0') || '-' || UNISTR('\23CF')
|| '|' || UNISTR('\23E9') || '-' || UNISTR('\23FA')
|| '|' || UNISTR('\24C2')
|| '|' || UNISTR('\25A0') || '-' || UNISTR('\25CF')
|| '|' || UNISTR('\25F0') || '-' || UNISTR('\25FF')
|| '|' || UNISTR('\2600') || '-' || UNISTR('\26FF')
|| '|' || UNISTR('\2700') || '-' || UNISTR('\2767')
|| '|' || UNISTR('\2790') || '-' || UNISTR('\27BF')
|| '|' || UNISTR('\2930') || '-' || UNISTR('\293F')
|| '|' || UNISTR('\2B00') || '-' || UNISTR('\2B1F')
|| '|' || UNISTR('\2B50') || '-' || UNISTR('\2B5F')
|| '|' || UNISTR('\3030') || '|' || UNISTR('\303D')
|| '|' || UNISTR('\3280') || '-' || UNISTR('\32CB')
|| ']'
|| '('
|| '[' ||UNISTR('\D83C')||UNISTR('\DFFB')||'-'||UNISTR('\D83C')||UNISTR('\DFFF')
|| '|'
|| UNISTR('\FE0F') || UNISTR('\20E3') || '?'
|| '|'
|| '[' ||UNISTR('\DB40')||UNISTR('\DC20')||'-'||UNISTR('\DB40')||UNISTR('\DC7E') || ']+' || UNISTR('\DB40')||UNISTR('\DC7F') || '?'
|| ')?'
|| '('
|| '[' || UNISTR('\200D') || ']'
|| '['
|| UNISTR('\D83C') || UNISTR('\DC00') || '-' || UNISTR('\D83C') || UNISTR('\DFFA')
|| '|' || UNISTR('\D83D') || UNISTR('\DC00') || '-' || UNISTR('\D83D') || UNISTR('\DFFF')
|| '|' || UNISTR('\D83E') || UNISTR('\DD0C') || '-' || UNISTR('\D83E') || UNISTR('\DEFF')
|| '|' || UNISTR('\00A9') || '|' || UNISTR('\00AE')
|| '|' || UNISTR('\203C') || '|' || UNISTR('\2049') || '|' || UNISTR('\2122') || '|' || UNISTR('\2139')
|| '|' || UNISTR('\2190') || '-' || UNISTR('\21AF')
|| '|' || UNISTR('\2310') || '-' || UNISTR('\231F')
|| '|' || UNISTR('\2326') || '-' || UNISTR('\232F')
|| '|' || UNISTR('\2380') || '-' || UNISTR('\238F')
|| '|' || UNISTR('\23C0') || '-' || UNISTR('\23CF')
|| '|' || UNISTR('\23E9') || '-' || UNISTR('\23FA')
|| '|' || UNISTR('\24C2')
|| '|' || UNISTR('\25A0') || '-' || UNISTR('\25CF')
|| '|' || UNISTR('\25F0') || '-' || UNISTR('\25FF')
|| '|' || UNISTR('\2600') || '-' || UNISTR('\26FF')
|| '|' || UNISTR('\2700') || '-' || UNISTR('\2767')
|| '|' || UNISTR('\2790') || '-' || UNISTR('\27BF')
|| '|' || UNISTR('\2930') || '-' || UNISTR('\293F')
|| '|' || UNISTR('\2B00') || '-' || UNISTR('\2B1F')
|| '|' || UNISTR('\2B50') || '-' || UNISTR('\2B5F')
|| '|' || UNISTR('\3030') || '|' || UNISTR('\303D')
|| '|' || UNISTR('\3280') || '-' || UNISTR('\32CB')
|| ']'
|| '('
|| '[' ||UNISTR('\D83C')||UNISTR('\DFFB')||'-'||UNISTR('\D83C')||UNISTR('\DFFF')
|| '|'
|| UNISTR('\FE0F') || UNISTR('\20E3') || '?'
|| '|'
|| '[' ||UNISTR('\DB40')||UNISTR('\DC20')||'-'||UNISTR('\DB40')||UNISTR('\DC7E') || ']+' || UNISTR('\DB40')||UNISTR('\DC7F') || '?'
|| ')?'
|| ')*'
) FROM DUAL;
说明:由于受REGEXP_SUBSTR()中正则表达式长度的限制,经过不断测探和检查收敛后,将上面链接中PHP实现方式里面穷举出Emoji表情的方式,精简为如下范围列举的方式。这样会稍有误差,其覆盖的范围会略大于穷举的方式。也就是可能会有误杀,当某个非Emoji特殊字符,正好在这个范围之中,可能会被识别成Emoji表情。当然,在此范围内的所有符号,我也全部检查过,明显的非Emoji表情符号,也全部剔除了,误杀的概率还是极低的。
|| '['
|| UNISTR('\D83C') || UNISTR('\DC00') || '-' || UNISTR('\D83C') || UNISTR('\DFFF')
|| '|' || UNISTR('\D83D') || UNISTR('\DC00') || '-' || UNISTR('\D83D') || UNISTR('\DFFF')
|| '|' || UNISTR('\D83E') || UNISTR('\DD0C') || '-' || UNISTR('\D83E') || UNISTR('\DEFF')
|| '|' || UNISTR('\00A9') || '|' || UNISTR('\00AE')
|| '|' || UNISTR('\203C') || '|' || UNISTR('\2049') || '|' || UNISTR('\2122') || '|' || UNISTR('\2139')
|| '|' || UNISTR('\2190') || '-' || UNISTR('\21AF')
|| '|' || UNISTR('\2310') || '-' || UNISTR('\231F')
|| '|' || UNISTR('\2326') || '-' || UNISTR('\232F')
|| '|' || UNISTR('\2380') || '-' || UNISTR('\238F')
|| '|' || UNISTR('\23C0') || '-' || UNISTR('\23CF')
|| '|' || UNISTR('\23E9') || '-' || UNISTR('\23FA')
|| '|' || UNISTR('\24C2')
|| '|' || UNISTR('\25A0') || '-' || UNISTR('\25CF')
|| '|' || UNISTR('\25F0') || '-' || UNISTR('\25FF')
|| '|' || UNISTR('\2600') || '-' || UNISTR('\26FF')
|| '|' || UNISTR('\2700') || '-' || UNISTR('\2767')
|| '|' || UNISTR('\2790') || '-' || UNISTR('\27BF')
|| '|' || UNISTR('\2930') || '-' || UNISTR('\293F')
|| '|' || UNISTR('\2B00') || '-' || UNISTR('\2B1F')
|| '|' || UNISTR('\2B50') || '-' || UNISTR('\2B5F')
|| '|' || UNISTR('\3030') || '|' || UNISTR('\303D')
|| '|' || UNISTR('\3280') || '-' || UNISTR('\32CB')
|| ']'
至此,用Oracle中的正则表达式方法,实现了对所有的Emoji表情的识别。至于要将其转成十六进制UTF8编码,就简单了。现将个人实现的完成函数附上。
CREATE OR REPLACE FUNCTION F_CONVERT_EMOJI_TO_HEX(Inp_STR IN VARCHAR2) RETURN VARCHAR2 IS
--{
lv_inpStr VARCHAR2(2000 CHAR) := TRIM(Inp_STR);
lv_result VARCHAR2(32767 CHAR);
lv_emojiChar VARCHAR2(500 CHAR);
lv_emojiChar_dump VARCHAR2(500 CHAR);
lv_emojiChar_hex VARCHAR2(500 CHAR);
--}
BEGIN
--{
IF lv_inpStr IS NULL THEN
lv_result := '';
ELSE
lv_result := lv_inpStr;
--DBMS_OUTPUT.PUT_LINE('lv_result: ' || lv_inpStr);
lv_emojiChar := REGEXP_SUBSTR(lv_result,
'[#*0-9]' || UNISTR('\FE0F') || '?' || UNISTR('\20E3')
|| '|'
|| '[' || UNISTR('\D83C') || UNISTR('\DDE6') || '-' || UNISTR('\D83C') || UNISTR('\DDFF') || ']{2}'
|| '|'
|| '['
|| UNISTR('\D83C') || UNISTR('\DC00') || '-' || UNISTR('\D83C') || UNISTR('\DFFA')
|| '|' || UNISTR('\D83D') || UNISTR('\DC00') || '-' || UNISTR('\D83D') || UNISTR('\DFFF')
|| '|' || UNISTR('\D83E') || UNISTR('\DD0C') || '-' || UNISTR('\D83E') || UNISTR('\DEFF')
|| '|' || UNISTR('\00A9') || '|' || UNISTR('\00AE')
|| '|' || UNISTR('\203C') || '|' || UNISTR('\2049') || '|' || UNISTR('\2122') || '|' || UNISTR('\2139')
|| '|' || UNISTR('\2190') || '-' || UNISTR('\21AF')
|| '|' || UNISTR('\2310') || '-' || UNISTR('\231F')
|| '|' || UNISTR('\2326') || '-' || UNISTR('\232F')
|| '|' || UNISTR('\2380') || '-' || UNISTR('\238F')
|| '|' || UNISTR('\23C0') || '-' || UNISTR('\23CF')
|| '|' || UNISTR('\23E9') || '-' || UNISTR('\23FA')
|| '|' || UNISTR('\24C2')
|| '|' || UNISTR('\25A0') || '-' || UNISTR('\25CF')
|| '|' || UNISTR('\25F0') || '-' || UNISTR('\25FF')
|| '|' || UNISTR('\2600') || '-' || UNISTR('\26FF')
|| '|' || UNISTR('\2700') || '-' || UNISTR('\2767')
|| '|' || UNISTR('\2790') || '-' || UNISTR('\27BF')
|| '|' || UNISTR('\2930') || '-' || UNISTR('\293F')
|| '|' || UNISTR('\2B00') || '-' || UNISTR('\2B1F')
|| '|' || UNISTR('\2B50') || '-' || UNISTR('\2B5F')
|| '|' || UNISTR('\3030') || '|' || UNISTR('\303D')
|| '|' || UNISTR('\3280') || '-' || UNISTR('\32CB')
|| ']'
|| '('
|| '[' ||UNISTR('\D83C')||UNISTR('\DFFB')||'-'||UNISTR('\D83C')||UNISTR('\DFFF')
|| '|'
|| UNISTR('\FE0F') || UNISTR('\20E3') || '?'
|| '|'
|| '[' ||UNISTR('\DB40')||UNISTR('\DC20')||'-'||UNISTR('\DB40')||UNISTR('\DC7E') || ']+' || UNISTR('\DB40')||UNISTR('\DC7F') || '?'
|| ')?'
|| '('
|| '[' || UNISTR('\200D') || ']'
|| '['
|| UNISTR('\D83C') || UNISTR('\DC00') || '-' || UNISTR('\D83C') || UNISTR('\DFFA')
|| '|' || UNISTR('\D83D') || UNISTR('\DC00') || '-' || UNISTR('\D83D') || UNISTR('\DFFF')
|| '|' || UNISTR('\D83E') || UNISTR('\DD0C') || '-' || UNISTR('\D83E') || UNISTR('\DEFF')
|| '|' || UNISTR('\00A9') || '|' || UNISTR('\00AE')
|| '|' || UNISTR('\203C') || '|' || UNISTR('\2049') || '|' || UNISTR('\2122') || '|' || UNISTR('\2139')
|| '|' || UNISTR('\2190') || '-' || UNISTR('\21AF')
|| '|' || UNISTR('\2310') || '-' || UNISTR('\231F')
|| '|' || UNISTR('\2326') || '-' || UNISTR('\232F')
|| '|' || UNISTR('\2380') || '-' || UNISTR('\238F')
|| '|' || UNISTR('\23C0') || '-' || UNISTR('\23CF')
|| '|' || UNISTR('\23E9') || '-' || UNISTR('\23FA')
|| '|' || UNISTR('\24C2')
|| '|' || UNISTR('\25A0') || '-' || UNISTR('\25CF')
|| '|' || UNISTR('\25F0') || '-' || UNISTR('\25FF')
|| '|' || UNISTR('\2600') || '-' || UNISTR('\26FF')
|| '|' || UNISTR('\2700') || '-' || UNISTR('\2767')
|| '|' || UNISTR('\2790') || '-' || UNISTR('\27BF')
|| '|' || UNISTR('\2930') || '-' || UNISTR('\293F')
|| '|' || UNISTR('\2B00') || '-' || UNISTR('\2B1F')
|| '|' || UNISTR('\2B50') || '-' || UNISTR('\2B5F')
|| '|' || UNISTR('\3030') || '|' || UNISTR('\303D')
|| '|' || UNISTR('\3280') || '-' || UNISTR('\32CB')
|| ']'
|| '('
|| '[' ||UNISTR('\D83C')||UNISTR('\DFFB')||'-'||UNISTR('\D83C')||UNISTR('\DFFF')
|| '|'
|| UNISTR('\FE0F') || UNISTR('\20E3') || '?'
|| '|'
|| '[' ||UNISTR('\DB40')||UNISTR('\DC20')||'-'||UNISTR('\DB40')||UNISTR('\DC7E') || ']+' || UNISTR('\DB40')||UNISTR('\DC7F') || '?'
|| ')?'
|| ')*');
--DBMS_OUTPUT.PUT_LINE('lv_emojiChar: ' || lv_emojiChar);
WHILE (lv_emojiChar IS NOT NULL ) LOOP
SELECT TRIM(DUMP(lv_emojiChar, 16)) INTO lv_emojiChar_dump FROM DUAL;
--DBMS_OUTPUT.PUT_LINE('lv_emojiChar_dump: ' || lv_emojiChar_dump);
/*f0,9f,91,a7,e2,80,8d,f0,9f,91,a6 -> \xF0\x9F\x91\xA7\xE2\x80\x8D\xF0\x9F\x91\xA6 */
lv_emojiChar_hex := '\x'|| REPLACE(UPPER(SUBSTR(lv_emojiChar_dump, INSTR(lv_emojiChar_dump, ':')+2)), ',', '\x');
--DBMS_OUTPUT.PUT_LINE('lv_emojiChar_hex: ' || lv_emojiChar_hex);
lv_result := REPLACE(lv_result, lv_emojiChar, lv_emojiChar_hex);
--DBMS_OUTPUT.PUT_LINE('lv_result: ' || lv_result);
lv_emojiChar := REGEXP_SUBSTR(lv_result,
'[#*0-9]' || UNISTR('\FE0F') || '?' || UNISTR('\20E3')
|| '|'
|| '[' || UNISTR('\D83C') || UNISTR('\DDE6') || '-' || UNISTR('\D83C') || UNISTR('\DDFF') || ']{2}'
|| '|'
|| '['
|| UNISTR('\D83C') || UNISTR('\DC00') || '-' || UNISTR('\D83C') || UNISTR('\DFFA')
|| '|' || UNISTR('\D83D') || UNISTR('\DC00') || '-' || UNISTR('\D83D') || UNISTR('\DFFF')
|| '|' || UNISTR('\D83E') || UNISTR('\DD0C') || '-' || UNISTR('\D83E') || UNISTR('\DEFF')
|| '|' || UNISTR('\00A9') || '|' || UNISTR('\00AE')
|| '|' || UNISTR('\203C') || '|' || UNISTR('\2049') || '|' || UNISTR('\2122') || '|' || UNISTR('\2139')
|| '|' || UNISTR('\2190') || '-' || UNISTR('\21AF')
|| '|' || UNISTR('\2310') || '-' || UNISTR('\231F')
|| '|' || UNISTR('\2326') || '-' || UNISTR('\232F')
|| '|' || UNISTR('\2380') || '-' || UNISTR('\238F')
|| '|' || UNISTR('\23C0') || '-' || UNISTR('\23CF')
|| '|' || UNISTR('\23E9') || '-' || UNISTR('\23FA')
|| '|' || UNISTR('\24C2')
|| '|' || UNISTR('\25A0') || '-' || UNISTR('\25CF')
|| '|' || UNISTR('\25F0') || '-' || UNISTR('\25FF')
|| '|' || UNISTR('\2600') || '-' || UNISTR('\26FF')
|| '|' || UNISTR('\2700') || '-' || UNISTR('\2767')
|| '|' || UNISTR('\2790') || '-' || UNISTR('\27BF')
|| '|' || UNISTR('\2930') || '-' || UNISTR('\293F')
|| '|' || UNISTR('\2B00') || '-' || UNISTR('\2B1F')
|| '|' || UNISTR('\2B50') || '-' || UNISTR('\2B5F')
|| '|' || UNISTR('\3030') || '|' || UNISTR('\303D')
|| '|' || UNISTR('\3280') || '-' || UNISTR('\32CB')
|| ']'
|| '('
|| '[' ||UNISTR('\D83C')||UNISTR('\DFFB')||'-'||UNISTR('\D83C')||UNISTR('\DFFF')
|| '|'
|| UNISTR('\FE0F') || UNISTR('\20E3') || '?'
|| '|'
|| '[' ||UNISTR('\DB40')||UNISTR('\DC20')||'-'||UNISTR('\DB40')||UNISTR('\DC7E') || ']+' || UNISTR('\DB40')||UNISTR('\DC7F') || '?'
|| ')?'
|| '('
|| '[' || UNISTR('\200D') || ']'
|| '['
|| UNISTR('\D83C') || UNISTR('\DC00') || '-' || UNISTR('\D83C') || UNISTR('\DFFA')
|| '|' || UNISTR('\D83D') || UNISTR('\DC00') || '-' || UNISTR('\D83D') || UNISTR('\DFFF')
|| '|' || UNISTR('\D83E') || UNISTR('\DD0C') || '-' || UNISTR('\D83E') || UNISTR('\DEFF')
|| '|' || UNISTR('\00A9') || '|' || UNISTR('\00AE')
|| '|' || UNISTR('\203C') || '|' || UNISTR('\2049') || '|' || UNISTR('\2122') || '|' || UNISTR('\2139')
|| '|' || UNISTR('\2190') || '-' || UNISTR('\21AF')
|| '|' || UNISTR('\2310') || '-' || UNISTR('\231F')
|| '|' || UNISTR('\2326') || '-' || UNISTR('\232F')
|| '|' || UNISTR('\2380') || '-' || UNISTR('\238F')
|| '|' || UNISTR('\23C0') || '-' || UNISTR('\23CF')
|| '|' || UNISTR('\23E9') || '-' || UNISTR('\23FA')
|| '|' || UNISTR('\24C2')
|| '|' || UNISTR('\25A0') || '-' || UNISTR('\25CF')
|| '|' || UNISTR('\25F0') || '-' || UNISTR('\25FF')
|| '|' || UNISTR('\2600') || '-' || UNISTR('\26FF')
|| '|' || UNISTR('\2700') || '-' || UNISTR('\2767')
|| '|' || UNISTR('\2790') || '-' || UNISTR('\27BF')
|| '|' || UNISTR('\2930') || '-' || UNISTR('\293F')
|| '|' || UNISTR('\2B00') || '-' || UNISTR('\2B1F')
|| '|' || UNISTR('\2B50') || '-' || UNISTR('\2B5F')
|| '|' || UNISTR('\3030') || '|' || UNISTR('\303D')
|| '|' || UNISTR('\3280') || '-' || UNISTR('\32CB')
|| ']'
|| '('
|| '[' ||UNISTR('\D83C')||UNISTR('\DFFB')||'-'||UNISTR('\D83C')||UNISTR('\DFFF')
|| '|'
|| UNISTR('\FE0F') || UNISTR('\20E3') || '?'
|| '|'
|| '[' ||UNISTR('\DB40')||UNISTR('\DC20')||'-'||UNISTR('\DB40')||UNISTR('\DC7E') || ']+' || UNISTR('\DB40')||UNISTR('\DC7F') || '?'
|| ')?'
|| ')*');
--DBMS_OUTPUT.PUT_LINE('lv_emojiChar: ' || lv_emojiChar);
END LOOP;
END IF;
RETURN lv_result;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
--}
END F_TRANSLATE_EMOJI_TOHEX;
/
执行效果如下:
SELECT F_TRANSLATE_EMOJI_TOHEX ('Happy Birthday!🇺🇸#⃣👩❤️💋👨😶🌫️Happy Birthday!😀') FROM DUAL;
结果:
Happy Birthday!\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8\x23\xE2\x83\xA3\xF0\x9F\x91\xA9\xE2\x80\x8D\xE2\x9D\xA4\xEF\xB8\x8F\xE2\x80\x8D\xF0\x9F\x92\x8B\xE2\x80\x8D\xF0\x9F\x91\xA8\xF0\x9F\x98\xB6\xE2\x80\x8D\xF0\x9F\x8C\xAB\xEF\xB8\x8FHappy Birthday!\xF0\x9F\x98\x80
如果将程序中的输出放开,output打印日志如下:
lv_result: Happy Birthday!🇺🇸#⃣👩❤️💋👨😶🌫️Happy Birthday!😀
lv_emojiChar: 🇺🇸
lv_emojiChar_dump: Typ=1 Len=8: f0,9f,87,ba,f0,9f,87,b8
lv_emojiChar_hex: \xF0\x9F\x87\xBA\xF0\x9F\x87\xB8
lv_result: Happy Birthday!\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8#⃣👩❤️💋👨😶🌫️Happy Birthday!😀
lv_emojiChar: #⃣
lv_emojiChar_dump: Typ=1 Len=4: 23,e2,83,a3
lv_emojiChar_hex: \x23\xE2\x83\xA3
lv_result: Happy Birthday!\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8\x23\xE2\x83\xA3👩❤️💋👨😶🌫️Happy Birthday!😀
lv_emojiChar: 👩❤️💋👨
lv_emojiChar_dump: Typ=1 Len=27: f0,9f,91,a9,e2,80,8d,e2,9d,a4,ef,b8,8f,e2,80,8d,f0,9f,92,8b,e2,80,8d,f0,9f,91,a8
lv_emojiChar_hex: \xF0\x9F\x91\xA9\xE2\x80\x8D\xE2\x9D\xA4\xEF\xB8\x8F\xE2\x80\x8D\xF0\x9F\x92\x8B\xE2\x80\x8D\xF0\x9F\x91\xA8
lv_result: Happy Birthday!\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8\x23\xE2\x83\xA3\xF0\x9F\x91\xA9\xE2\x80\x8D\xE2\x9D\xA4\xEF\xB8\x8F\xE2\x80\x8D\xF0\x9F\x92\x8B\xE2\x80\x8D\xF0\x9F\x91\xA8😶🌫️Happy Birthday!😀
lv_emojiChar: 😶🌫️
lv_emojiChar_dump: Typ=1 Len=14: f0,9f,98,b6,e2,80,8d,f0,9f,8c,ab,ef,b8,8f
lv_emojiChar_hex: \xF0\x9F\x98\xB6\xE2\x80\x8D\xF0\x9F\x8C\xAB\xEF\xB8\x8F
lv_result: Happy Birthday!\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8\x23\xE2\x83\xA3\xF0\x9F\x91\xA9\xE2\x80\x8D\xE2\x9D\xA4\xEF\xB8\x8F\xE2\x80\x8D\xF0\x9F\x92\x8B\xE2\x80\x8D\xF0\x9F\x91\xA8\xF0\x9F\x98\xB6\xE2\x80\x8D\xF0\x9F\x8C\xAB\xEF\xB8\x8FHappy Birthday!😀
lv_emojiChar: 😀
lv_emojiChar_dump: Typ=1 Len=4: f0,9f,98,80
lv_emojiChar_hex: \xF0\x9F\x98\x80
lv_result: Happy Birthday!\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8\x23\xE2\x83\xA3\xF0\x9F\x91\xA9\xE2\x80\x8D\xE2\x9D\xA4\xEF\xB8\x8F\xE2\x80\x8D\xF0\x9F\x92\x8B\xE2\x80\x8D\xF0\x9F\x91\xA8\xF0\x9F\x98\xB6\xE2\x80\x8D\xF0\x9F\x8C\xAB\xEF\xB8\x8FHappy Birthday!\xF0\x9F\x98\x80
lv_emojiChar:
相关参考:
Unicode 与 UTF8的区别:
Unicode和UTF-8的区别_、wook的博客-CSDN博客
https://www.cnblogs.com/renlinsen/p/14206715.html
Emoji 表情:
Emoji unicode characters for use on the web
ORACLE正则表达式函数,参考:
Oracle 正则表达式详解(regexp_substr、regexp_instr、regexp_replace、regexp_like)_越努力越幸运再努力的博客-CSDN博客
Oracle dump()函数: