【问题标题】:Finding Emojis in Strings在字符串中查找表情符号
【发布时间】:2020-07-27 12:35:34
【问题描述】:

所以我试图在字符串中查找和替换表情符号。到目前为止,这是我使用正则表达式的方法。

const replaceEmojis = function (string) {
    String.prototype.regexIndexOf = function (regex, startpos) {
        const indexOf = this.substring(startpos || 0).search(regex);
        return (indexOf >= 0) ? (indexOf + (startpos || 0)) : indexOf;
    }
    // generate regexp
    let regexp;
    try {
        regexp = new RegExp('\\p{Emoji}', "gu");
    } catch (e) {
        //4 firefox <3
        regexp = new RegExp(`(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])`, 'g');
    }

    // get indices of all emojis
    function getIndicesOf(searchStr, str) {
        let index, indices = [];

        function getIndex(startIndex) {
            index = str.regexIndexOf(searchStr, startIndex);
            if (index === -1) return;
            indices.push(index);
            getIndex(index + 1)
        }

        getIndex(0);

        return indices;
    }

    const emojisAt = getIndicesOf(regexp, string);

    // replace emojis with SVGs
    emojisAt.forEach(index => {
        // got nothing here yet
        // const unicode = staticHTML.charCodeAt(index); //.toString(16);
    })

这样做的问题是我只得到一个带有索引的数组,其中表情符号在字符串中。但是只有这些索引我无法替换它们,因为我不知道它们占用了多少(UTF-16)字节。 为了替换它们,我需要知道我要替换的是什么表情符号。

那么,有没有办法同时获得表情符号的长度?还是有比我更好(也许更简单)的方式来替换表情符号?

【问题讨论】:

  • 您认为表情符号到底是什么?有成千上万这样的东西。你的目标是什么?
  • @Brad 我的意思是所有Emojis in Unicode 包括肤色,基本上是您使用/\p{Emoji}/gu 表达式选择的所有内容。我想用表情符号的 SVG 替换它们。这个想法是找到一个表情符号,获取它的 unicode(不是 charcode)并用 SVG 替换它。然而,一个(长)unicode 会使用多个 UTF-16 字符代码进行编码,因此表情符号是各种 UTF-16 字符长,所以我需要知道一个表情符号要替换它的“长度”。

标签: javascript regex unicode emoji


【解决方案1】:

好吧,原来我只是有点精神障碍。
要找到表情符号,我不需要像 WolverinDEV 提到的那样获取索引。尽管仅将 string.replace/\p{Emoji}/gu 一起使用是行不通的,因为这会分解,例如??‍♂️变成?、?和♂。所以我调整了正则表达式来解决这个问题:/[\p{Emoji}\u200d]+/gu。现在表情符号完整返回,因为包含零宽度连接器。
这就是我得到的(如果有人关心的话):

const replaceEmojis = function (string) {
    const emojis = string.match(/[\p{Emoji}\u200d]+/gu);
    // console.log(emojis);

    // replace emojis with SVGs
    emojis.forEach(emoji => {
        // get the unicodes of the emoji
        let unicode = "";

        function getNextChar(pointer) {
            const subUnicode = emoji.codePointAt(pointer);
            if (!subUnicode) return;
            unicode += '-' + subUnicode.toString(16);
            getNextChar(++pointer);
        }

        getNextChar(0);

        unicode = unicode.substr(1); // remove the beginning dash '-'
        console.log(unicode.toUpperCase());

        // replace emoji here
        // string = string.replace(emoji, `<svg src='path/to/svg/${unicode}.svg'>`)
    })

    return string;
}

这仍然需要工作,例如因为在输出的 unicode 中有Low Surrogates,但从根本上说,这是可行的。

编辑:

第一次改进:
您可能不需要这个,但要摆脱低代理字符,请在 getNextChar() 中添加一个条件

if (!(subUnicode >= 56320 && subUnicode <= 57343)) unicode += '-' + subUnicode.toString(16);

这仅在不是低代理字符时添加字符代码。

第二次改进:
将变体选择器 16 (U+FE0F) 添加到正则表达式以选择更多表情符号整体:

/[\p{Emoji}\u200d\ufe0f]+/gu

【讨论】:

【解决方案2】:

你已经有一个正常工作的正则表达式,所以你可以使用String.replace

string.replace(regexp, my_emojy => { 
    return "<an emoji was here>";
});

所以您根本不需要查找任何索引。

【讨论】:

  • 是的!谢谢你的回答!我重新考虑了这个漏洞,还看到string.match(regexp) 是一个选项,可以只获取表情符号,然后用string.replace 替换forEach 中的它们。尽管您的解决方案要简单得多,但我会单独进行,因为不幸的是我必须考虑所有标识符(肤色、性别、连接器、变体选择器等)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-31
  • 2015-08-25
  • 2013-10-09
  • 2023-03-03
  • 1970-01-01
  • 2014-04-06
  • 1970-01-01
相关资源
最近更新 更多