【问题标题】:Why do Unicode emoji property escapes match numbers?为什么 Unicode 表情符号属性会转义匹配数字?
【发布时间】:2021-01-30 23:39:15
【问题描述】:

我发现了一种很棒的方法来使用不使用“巨大魔法范围”的正则表达式检测表情符号,方法是使用Unicode property escape

console.log(/\p{Emoji}/u.test('flowers ????????????')) // true
console.log(/\p{Emoji}/u.test('flowers')) // false

但是当我分享这个知识in this answer,@Bronzdragon 注意到\p{Emoji} 也匹配数字!这是为什么?数字不是表情符号?

console.log(/\p{Emoji}/u.test('flowers 123')) // unexpectdly true

// regex-only workaround by @Bonzdragon
const regex = /(?=\p{Emoji})(?!\p{Number})/u;
console.log(
  regex.test('flowers'), // false, as expected
  regex.test('flowers 123'), // false, as expected
  regex.test('flowers 123 ????????????'), // true, as expected
  regex.test('flowers ????????????'), // true, as expected
)

// more readable workaround
const hasEmoji = str => {
  const nbEmojiOrNumber = (str.match(/\p{Emoji}/gu) || []).length;
  const nbNumber = (str.match(/\p{Number}/gu) || []).length;
  return nbEmojiOrNumber > nbNumber;
}
console.log(
  hasEmoji('flowers'), // false, as expected
  hasEmoji('flowers 123'), // false, as expected
  hasEmoji('flowers 123 ????????????'), // true, as expected
  hasEmoji('flowers ????????????'), // true, as expected
)

【问题讨论】:

  • 请注意,解决方法对于 '123 花 ????????????' 也失败了例如 - 应该返回 true,因为它肯定有表情符号。
  • 为什么不直接删除所有数字然后进行检查?
  • 问题不是如何解决它 (here is a fix),问题是为什么。否则,让我们关闭它。
  • 我认为答案是here 以及该帖子之后的所有线程。 这不是错误。 #0-9Emoji 字符,默认情况下具有文本表示,符合 Unicode 标准。
  • This post 更详细,您可能可以使用/\p{Extended_Pictographic}/u 正则表达式来匹配表情符号,除了一些仍然是表情符号的键帽基本字符。

标签: javascript regex emoji


【解决方案1】:

根据this post、digtis、#*、ZWJ 和一些其他字符包含设置为 YesEmoji 属性,这意味着 数字被认为是有效的表情符号字符

0023          ; Emoji_Component      #  1.1  [1] (#️)       number sign
002A          ; Emoji_Component      #  1.1  [1] (*️)       asterisk
0030..0039    ; Emoji_Component      #  1.1 [10] (0️..9️)    digit zero..digit nine
200D          ; Emoji_Component      #  1.1  [1] (‍)        zero width joiner
20E3          ; Emoji_Component      #  3.0  [1] (⃣)       combining enclosing keycap
FE0F          ; Emoji_Component      #  3.2  [1] ()        VARIATION SELECTOR-16
1F1E6..1F1FF  ; Emoji_Component      #  6.0 [26] (?..?)    regional indicator symbol letter a..regional indicator symbol letter z
1F3FB..1F3FF  ; Emoji_Component      #  8.0  [5] (?..?)    light skin tone..dark skin tone
1F9B0..1F9B3  ; Emoji_Component      # 11.0  [4] (?..?)    red-haired..white-haired
E0020..E007F  ; Emoji_Component      #  3.1 [96] (?..?)      tag space..cancel tag

例如,1 是一个数字,但与U+FE0FU+20E3 字符组合时变成表情符号:1️⃣:

console.log("1\uFE0F\u20E3 2\uFE0F\u20E3 3\uFE0F\u20E3 4\uFE0F\u20E3 5\uFE0F\u20E3 6\uFE0F\u20E3 7\uFE0F\u20E3 8\uFE0F\u20E3 9\uFE0F\u20E3 0\uFE0F\u20E3")

如果要避免匹配数字,请使用Extended_PictographicUnicode 类别类:

Extended_Pictographic 字符包含除某些 Emoji_Components 之外的所有 Emoji 字符。

因此,您可以使用/\p{Extended_Pictographic}/gu 匹配大多数表情符号,或使用/\p{Extended_Pictographic}/u 测试单个表情符号,或使用/[\p{Extended_Pictographic}\u{1F3FB}-\u{1F3FF}\u{1F9B0}-\u{1F9B3}]/u 匹配表情符号恰当和浅色皮肤与深色皮肤模式字符和红发到白头发的字符:

const regex_emoji = /[\p{Extended_Pictographic}\u{1F3FB}-\u{1F3FF}\u{1F9B0}-\u{1F9B3}]/u;
console.log( regex_emoji.test('flowers 123') );     // => false
console.log( regex_emoji.test('flowers ???') ); // => true

【讨论】:

  • 感谢您为回答所做的努力,如果您能告诉我为什么 unicode 联盟认为 0123456789#* 是完美的表情符号!
  • @NinoFiliu 我添加了一个演示,展示了1 如何变成表情符号。
猜你喜欢
  • 2021-09-14
  • 1970-01-01
  • 2018-10-11
  • 2015-10-18
  • 2015-01-15
  • 1970-01-01
  • 1970-01-01
  • 2019-01-27
  • 2017-05-27
相关资源
最近更新 更多