国际化字符
由于 JavaScript 最初的实现非常简单,而且这种简单的处理方式后来也成了标准,因此 JavaScript 正则表达式处理非英语字符时非常无力。例如,就 JavaScript 的正则表达式而言,“单词字符”只是 26 个拉丁字母(大写和小写)和数字,而且由于某些原因还包括下划线字符。像α
或β
这种明显的单词字符,则无法匹配\w
(会匹配大写的\W
,因为它们属于非单词字符)。
由于奇怪的历史性意外,\s
(空白字符)则没有这种问题,会匹配所有 Unicode 标准中规定的空白字符,包括不间断空格和蒙古文元音分隔符。
另一个问题是,默认情况下,正则表达式使用代码单元,而不是实际的字符,正如第 5 章中所讨论的那样。 这意味着由两个代码单元组成的字符表现很奇怪。
console.log(/\ud83c\udf4e{3}/.test("\ud83c\udf4e\ud83c\udf4e\ud83c\udf4e"));
// → false
console.log(/<.>/.test("<\ud83c\udf39>"));
// → false
console.log(/<.>/u.test("<\ud83c\udf39>"));
// → true
问题是第一行中的"\ud83c\udf4e"
(emoji 苹果)被视为两个代码单元,而{3}
部分仅适用于第二个。 与之类似,点匹配单个代码单元,而不是组成玫瑰 emoji 符号的两个代码单元。
你必须在正则表达式中添加一个u
选项(表示 Unicode),才能正确处理这些字符。 不幸的是,错误的行为仍然是默认行为,因为改变它可能会导致依赖于它的现有代码出现问题。
尽管这是刚刚标准化的,在撰写本文时尚未得到广泛支持,但可以在正则表达式中使用\p
(必须启用 Unicode 选项)以匹配 Unicode 标准分配了给定属性的所有字符。
console.log(/\p{Script=Greek}/u.test("α"));
// → true
console.log(/\p{Script=Arabic}/u.test("α"));
// → false
console.log(/\p{Alphabetic}/u.test("α"));
// → true
console.log(/\p{Alphabetic}/u.test("!"));
// → false
Unicode 定义了许多有用的属性,尽管找到你需要的属性可能并不总是没有意义。 你可以使用\p{Property=Value}
符号来匹配任何具有该属性的给定值的字符。 如果属性名称保持不变,如\p{Name}
中那样,名称被假定为二元属性,如Alphabetic
,或者类别,如Number
。