Miscellaneous Symbols and Pictographs是一个Unicode块,其中包含气象和天文符号,表情符号字符(主要是与日本电话运营商的Shift JIS实现兼容)以及最初来自Microsoft Windows中的Wingdings和Webdings字体的字符。

所引用的维基百科文章指定的Unicode范围是U+1F300..U+1F5FF

但是,如果我从列表中选择一个表情符号并进行正则表达式匹配,它将失败。

var a = "🌍";
var matched = a.match(/[\u1F300-\u1F5FF]/);


matched始终为null。这是为什么?我在哪里出错?

最佳答案

问题

Java已有Unicode Problem一段时间了。超出U + 0000 ... U + FFFF范围的Unicode代码点被称为星体代码点,并且存在问题,因为它们不易通过正则表达式进行匹配:

// `🌍` is an astral symbol because its codepoint value
//  of U+1F30D is outside the range U+0000...U+FFFF
//  Astral symbols do not work with regular expressions as expected
var regex = /^[bc🌍]$/;
console.log(
    regex.test('a'),  // false
    regex.test('b'),  // true
    regex.test('c'),  // true
    regex.test('🌍')  // false (!)
);
console.log('🌍'.match(regex)); // null (!)


原因是因为此一个星体代码点实际上是由两部分组成,或更确切地说,由两个“代码单元”组成,并且这两个代码单元结合在一起形成了字符。

console.log("\u1F30D")      // Doesn't work
console.log("\uD83C\uDF0D") // 🌍


星号🌍实际上由两个代码单元组成:🌍= U + D83C + U + DF0D!
因此,如果要匹配此星号,则必须使用以下正则表达式和匹配器:

var regex = /^([bc]|\uD83C\uDF0D)$/;
console.log(
    regex.test('a'),  // false
    regex.test('b'),  // true
    regex.test('c'),  // true
    regex.test('\uD83C\uDF0D')  // true
);
console.log('\uD83C\uDF0D'.match(regex)); // { 0: "🌍", 1: "🌍", index: 0 ... }


所有星体符号都有此分解。惊讶吗好吧,也许你应该-这种情况很少发生!它仅在很少使用的星体代码点发生。我本人和全世界其他人使用的大多数代码点都不是星形的-它们在U + 0000 ... U + FFFF的范围内,因此我们通常不会看到此问题。表情符号是此规则的新例外-所有表情符号都是星号符号,并且由于社交媒体的使用,它们在全球范围内的使用日益广泛。

不幸的是,使用这样的代码单元是Unicode的实现细节,而Java程序员对此却很陌生。由于尚不清楚是使用字符逐字(🌍)还是使用代码单元分解(U + D83C + U + DF0D),无论何时使用诸如matchtest,。之类的字符串函数,它都容易引起程序员的困惑。 ..被使用;或每当使用正则表达式和字符串文字时。但是语言设计者和实现者正在努力改进。

解决方案

ECMAScript 6(ES6)的最新功能是对正则表达式匹配的introduction of a u flag。这使您可以按代码点进行匹配,而不是按代码单位进行匹配(默认)。

var regex = /^[bc🌍]$/u; // <-- u flag added
console.log(
    regex.test('a'), // false
    regex.test('b'), // true
    regex.test('c'), // true
    regex.test('🌍')  // true <-- it now works!
);


通过使用u标志,您不必担心代码点是否为星体代码点,也不必在代码单元之间来回转换。 u标志使正则表达式以直观的方式工作-即使是表情符号!但是,并非每个版本的Node.js以及每个浏览器都支持此新功能。为了支持所有环境,您可以使用regenerate之类的库。

10-06 05:19
查看更多