Oracle 正则式匹配识别Emoji表情符号

        最近接到一个将字符串中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表情的方法。

匹配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

深入理解Emoji(三) —— Emoji详解 - 简书

ORACLE正则表达式函数,参考:

Oracle 正则表达式详解(regexp_substr、regexp_instr、regexp_replace、regexp_like)_越努力越幸运再努力的博客-CSDN博客

Oracle dump()函数:

Oracle dump()函数_oracle dump函数_酒红的博客-CSDN博客

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值