\p{…} 属性类:用码点的 Unicode 档案来匹配
字符的编码那页讲了字符的编号(code point)与存储(UTF-16 / UTF-8)。这页讲第三样:
每个编号在 Unicode Character Database (UCD) 里都有一份档案——名字、
General_Category(它是字母 / 数字 / 标点…)、Script(它属于哪套文字)、
外加几十个二元属性(White_Space?Math?…的勾选框)。\p{…} 就是「按档案匹配」:
不必手写 [一-鿿] 这种码位区间,直接说「我要 \p{Script=Han}」。
\P{…} 是取反;两者都必须开 u 或 v 标志——
没有标志时 \p 只是字面量 p。
JS 里 \p{…} 的三种合法写法
| 写法 | 查档案的哪一栏 | 例子 |
|---|---|---|
\p{L} / \p{Lu} | General_Category(可省 gc=) | \p{L} ≡ \p{gc=L} ≡ \p{General_Category=L} |
\p{Script=Han} | Script / Script_Extensions | \p{sc=Han}、\p{scx=Han} |
\p{White_Space} | 二元属性(名字单独写) | \p{Math}、\p{Alphabetic}、\p{Emoji} |
\p{X}),引擎按「二元属性名,或 General_Category 的值」解析——
所以 \p{L} 是 gc 缩写、\p{Math} 是二元属性,写法看着一样,查的栏不同。
拼写是严格的:大小写、下划线都不能错,\p{whitespace} 直接 SyntaxError。
没有第四种——档案里还有一栏 Block(住址),JS 的 \p{} 不支持,见本页末尾。
码点探针:查一个字符的档案
输入一个字符,实时用原生 /\p{…}/u 把它的档案逐栏测出来。试试几个反直觉的:
𝑥(数学斜体)是字母、Script 却是 Common;、(顿号)不是 sc=Han;
½ 是数字(N)却不是十进制数字(Nd)。末行还附上 Block(住址)——
它是 \p{} 查不到的第四栏(见页末),这里用内嵌的官方区间表补出来:
² 住 Latin-1 Supplement、上标 ⁰ 住 Superscripts and Subscripts。
档案各栏(前三栏原生 /\p{…}/u 实测,末行 Block 查内嵌区间表)
第一栏 General_Category:七大类 30 小类
每个码点恰好属于一个 gc 小类;小类首字母就是大类。全量实测的基数(随 Unicode 版本微涨):
| 大类 | 含义 | 码点数 | 小类 | 例子 |
|---|---|---|---|---|
\p{L} | Letter 字母 | 145 672 | Lu Ll Lt Lm Lo | A é 中 ٱ 𝑥 |
\p{M} | Mark 标记(组合用) | 2 543 | Mn Mc Me | é 拆开后的 ◌́ |
\p{N} | Number 数字 | 1 924 | Nd Nl No | 7 ٧ Ⅻ ① ½ |
\p{P} | Punctuation 标点 | 856 | Pc Pd Ps Pe Pi Pf Po | , 、 « » _ |
\p{S} | Symbol 符号 | 8 617 | Sm Sc Sk So | + € ^ 😀 |
\p{Z} | Separator 分隔 | 19 | Zs Zl Zp | 空格 NBSP 全角空格 |
\p{C} | Other 其他 | 954 481 | Cc Cf Cs Co Cn | 控制符 ZWJ 未分配区 |
\p{C} 是大头,因为 U+0000~U+10FFFF 共 1 114 112 个码位里大部分还没分配(Cn)。
另外注意 emoji 😀 的 gc 是 So(其他符号)——「是不是 emoji」记在二元属性栏,不在 gc 栏。
想细看 \p{P} 标点的 7 个子类(Pc/Pd/Ps/Pe/Pi/Pf/Po)、脚注符号 * † ‡ § ¶ ‖ 为什么全是 Po、
以及开 / 闭括号数量为什么配不齐,见 \p{P} 标点七子类页。
把一段文本逐码点按大类着色,看看 gc 怎么切分真实文本:
\w \d 的 ASCII 视野 vs \p{…} 的 Unicode 视野
syntax 页的 \w \d 是钉死的 ASCII 集合:\w = [A-Za-z0-9_]、\d = [0-9],
开了 u 也不变。要按「档案」理解的字母 / 数字,得用 \p{L} / \p{Nd}(每格实时测出):
\p{L},\w 连 é 都不认;
其二 \p{Nd}(十进制位)≠ \p{N}(一切数字)——① ½ Ⅻ 是 N 却非 Nd,
解析数值时别把 ½ 当数位收进来;其三 _ 在 \w 里却既非字母也非数字(gc 是 Pc 连接标点)。
第二栏 Script:这是哪套文字 —— 以及 sc 和 scx 的差别
Script(sc)给每个码点记一个主属文字;但很多字符是几套文字共用的——
顿号 、 中日韩都用,长音符 ー 平/片假名都用,它们的 sc 只能记 Common。
Script_Extensions(scx)记的才是「哪些文字在用它」这个集合。
选一套文字、切换 sc / scx,看高亮差在哪:
\p{scx=…} 通常更接近直觉——
\p{sc=Han} 会把 、 。 这些 CJK 标点漏在外面(它们 sc=Common)。
顺带:𝕏 𝑥 这类数学字母的 Script 也是 Common——「长得像哪国字」不等于「属于哪套文字」。
第三栏 二元属性:档案里的几十个勾选框
gc 和 Script 每栏只有一个值;二元属性则是一排独立的 Yes/No 勾选框,一个码点可以同时勾中好几个。
JS 支持几十个,常用的如 \p{White_Space}、\p{Math}、\p{Alphabetic}、
\p{Uppercase}、\p{ASCII},以及 emoji 六属性页整页在讲的
\p{Emoji} 一家。挑两个看它们和「近亲」差在哪:
\p{White_Space}(25 个)vs \s —— 两份名单高度重合但不相等(每格实时测出):
U+FEFF 算 \s 却不算 \p{White_Space}(ES 把 ZWNBSP 纳入 WhiteSpace,Unicode 档案里它是 Cf 格式字符);
NEL U+0085 算 \p{White_Space} 却不算 \s。
其余成员一致——空白与换行页的完整清单讲的就是 \s 这份名单。
\p{Math}(2 322 个)vs \p{Sm}(960 个) —— 二元属性可以跨着 gc 切:
Math = Sm 全集 + 一批 gc 是字母 / 标点的「数学用」字符:
𝑥(数学斜体)、ℵ(阿列夫)gc 都是字母,却勾了 Math;
普通的 x 反而 Math=No。这正是二元属性的价值:「数学符号」这个概念
横跨 Sm / L / P 好几个 gc 类,只有档案里单独一栏才装得下。
同理 \p{Alphabetic}(147 421)也比 \p{L}(145 672)大——多出 Nl 与一批组合标记。
想看 2322 个 Math 字符全名单(按 block 分组、可搜索),见 \p{Math} 全量速查页。
还有一栏 Block(住址)—— JS 的 \p{} 不支持
档案里还有一栏 Block:码点住在哪个连续码位区段,比如 ∑ 住在
Mathematical Operators(U+2200~22FF)、中 住在
CJK Unified Ideographs(U+4E00~9FFF)。但 JS 的 \p{}
只支持 gc / Script(_Extensions) / 二元属性三种,Block 写法直接 SyntaxError
(Java 的 \p{InGreek}、.NET 的 \p{IsGreek}、Python regex 模块的
\p{Block=…} 才有)。想按 block 匹配,JS 只能手写码位区间。下面三条实测:
\p{} 查不到,不等于查不出——
本系列 regex.js 内嵌了一份官方 Blocks.txt(Unicode 17.0.0)的
区间表,blockOf(cp) 二分一查就知道任意码点的住址。所以探针末行能告诉你
² 住 Latin-1 Supplement、上标 ⁰ 住 Superscripts and Subscripts、𝑥 住 Mathematical Alphanumeric Symbols。
、 Script 是 Common);其二 同一类字符散落在多个 block
(上面实测:± × ÷ 住 Latin-1、𝑥 住 Mathematical Alphanumeric Symbols,
手写 U+2200~22FF 区间全漏掉,\p{Math} 一个不漏)。按「身份」查档案,几乎总比按「住址」圈选区间更可靠。
全量速查:346 个 block 的住址簿
既然内嵌了整张 Blocks.txt,索性把它全列出来——
Unicode 17.0.0 共 346 个具名 block(其余空隙是 No_Block)。按码位平面分段,
搜索框支持三种查法:块名(忽略大小写 / 空格 / 连字符,如 superscript、latin1)、
码点 hex(如 2070 或 U+2070 → 落在哪个 block)、或直接粘一个字符。
\s 完整清单对应这页的
White_Space 勾选框;emoji 六属性页讲的
\p{Emoji} 一家就是六个二元属性;自研引擎页的
@vega/parsing/regex 同样支持 gc / sc / scx / 二元属性三种写法、同样不支持 Block——
名字解析也按 JS 的严格拼写来。