JavaScript 中字符串使用的编码格式 Unicode 对于不同的字符(更严谨地说,码位)有大量的类别。这些类别描述了这个字符的“种类”和技术性细节。
在正则表达式中可以使用 \p{…}
来设置这些类别。注意此时 'u'
flag 不可缺少。
举个例子,\p{letter}
在任何一个语言中都表示一个字母。\p{L}
是它的简写形式。
以下是所有主要类别:
L
:
Ll
,修饰语 Lm
,大写首字母 Lt
,全部大写 Lu
,其他 Lo
N
:
Nd
,字母 Nl
,其他 No
P
:
Pc
,中划线 Pd
,引号 Pi
,引回 Pf
,开始 Ps
,结束 Pe
,其他 Po
M
:
Mc
,包围字符(一个或多个字符被另一些字符包围)Me
,组合字符(无间隔)Mn
S
:
Sc
,修饰符号 Sk
,数学 Sm
,其他 So
Z
:
Zl
,段落 Zp
,空格 Zs
C
:
Cc
,格式符 Cf
,未提供的 Cn
,非公用的 Co
,帮助符 Cs
更多信息
在 http://cldr.unicode.org/unicode-utilities/list-unicodeset 中你可以看到各种类别下的字符。
你也可以在 Character Property Index 探索这些类别。
在 https://www.unicode.org/Public/UCD/latest/ucd/ ,你可以看到完整的 Unicode 数据库(包含对类别的说明)。
还有其他的一些派生类别,如:
Alphabetic
(Alpha
),它包括字母 L
,用字母表示的数字 Nl
(如罗马数字 Ⅻ),还有一些其他的符号 Other_Alphabetic
(OAltpa
)。Hex_Digit
包含十六进制中用到的“数字”:0-9
,a-f
。举个例子,这个六位十六进制数:
let reg = /\p{Hex_Digit}{6}/u; // flag 'u' is required (注意 flag 'u' 是必须的)
alert("color: #123ABC".match(reg)); // 123ABC
还有有值的类别。如,Unicode “Script”(脚本,一种书写方式)可以表达西里尔字母、希腊文、阿拉伯语和中文等等。
要对一个单一的书写系统进行搜索,就要另外提供 Script=
。如,要搜索西里尔字母,应使用 \p{sc=Cyrillic}
,而对于汉字,应使用 \p{sc=Han}
,等等。以下是使用这种特性的代码片段:
let regexp = /\p{sc=Han}+/gu; // get chinese words (获得中文字符)
let str = `Hello Привет 你好 123_456`;
alert( str.match(regexp) ); // 你好
写对于所有语言都适用的 \w
请给所有的语言写一个“全面的” \w
的正则表达式。这一问题在很多有针对 Unicode 优化的正则表达式特性的编程语言中都有标准解决方式,如 Perl。
/[\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]/u
请跟我一起对它进行分析。由于 \w
其实就是 [a-zA-Z0-9_]
,
所以这个字符集包含了:
Alphabetic
字母,Mark
重音,因为重音在 Unicode 中可能被表示为多个码位,Decimal_Number
数字,Connector_Punctuation
‘_’(下划线)和类似它(下划线)的字符,Join_Control
—— 用于将字连起形成连字(如在阿拉伯语中使用)的两个特殊的码位(hex 分别为 200c
和 200d
)或者,如果换用缩写(缩写列表):
let regexp = /([\p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C}]+)/gu;
let str = `Hello Привет 你好 123_456`;
alert( str.match(regexp) ); // Hello,Привет,你好,123_456
Java的使用
val = val.replaceAll(Pattern.compile("\\p{P}+", Pattern.UNICODE_CHARACTER_CLASS).pattern(), "");
val = val.replaceAll(Pattern.compile("\\w", Pattern.UNICODE_CHARACTER_CLASS).pattern(), "");