我正在使用 ICU4C 并尝试在 UTF-8 字符串中查找表情符号簇。这是迄今为止我得到的最接近的结果,但它错误地将简单字符“#”限定为表情符号(因为“#️⃣”以“#”开头,并且“可能”是一个表情符号,因此“#”确实带有属性 UCHAR_EMOJI
)。
我认为最好的办法是尝试获取属性RGI_Emoji
,如here所示。但这是一个“字符串”属性,而不是“代码点”属性,我不知道该怎么做。如果可以的话,我会将每个字符分析为“字符串”并测试该字符串属性。文档指出,目前,使用正则表达式无法获取“字符串”属性。
const std::string s8 = "#🤙🏿asd🧔🏼😵💫dds🫥😶🌫️🏌️♂️🇨🇦ds#️⃣🏋🏽ds👨👩👦👦ds👩🏾❤️💋👨🏼ds";
const icu::UnicodeString us = icu::UnicodeString::fromUTF8(s8);
UErrorCode status = U_ZERO_ERROR;
icu::BreakIterator* bi = icu::BreakIterator::createCharacterInstance(icu::Locale::getUS(), status);
bi->setText(us);
bool is_emoji = false;
for(int32_t e = bi->first(), b = e; e != icu::BreakIterator::DONE; b = e, e = bi->next())
{
// Analyze character for emoji-ness.
for(int32_t i = b; i != e; ++i)
{
std::cout << us.char32At(i) << ' ';
is_emoji = u_hasBinaryProperty(us.char32At(i), UProperty::UCHAR_EMOJI) || u_hasBinaryProperty(us.char32At(i), UProperty::UCHAR_EMOJI_COMPONENT);
}
if(is_emoji)
{
std::cout << "<- is emoji\n";
++emojis;
is_emoji = false;
}
else
{
std::cout << "<- is not emoji\n";
}
++characters;
}
delete bi;
最佳答案
看起来像u_stringHasBinaryProperty将使您能够访问 UCHAR_RGI_EMOJI
。请注意,此方法在 ICU 版本 < 70 中不可用。
我认为您需要区分由单个代码点组成的基本表情符号(例如 U+1F600 😀)和表情符号序列(例如 U+0023 U+FE0F U+20E3 #️⃣)。 basic emoji将同时设置 UCHAR_EMOJI
和 UCHAR_BASIC_EMOJI
属性,并取消设置 UCHAR_EMOJI_COMPONENT
; first code point in a sequence将设置 UCHAR_EMOJI
和 UCHAR_EMOJI_COMPONENT
,但不设置 UCHAR_BASIC
。 Subsequent code points将设置 UCHAR_EMOJI_COMPONENT
,但不会设置 UCHAR_EMOJI
(也不会设置 UCHAR_BASIC_EMOJI
)。
如果遇到“#”(基本上是设置了 UCHAR_EMOJI
和 UCHAR_EMOJI_COMPONENT
的任何代码点),则需要检查下一个代码点。仅当下一个代码点没有 UCHAR_EMOJI
但有 UCHAR_EMOJI_COMPONENT
时,“#”才是表情符号的一部分。
关于c++ - 如何测试字符串是否包含表情符号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73634556/