regex 总览待审核
基础 · 码点的档案 \p{…}

\p{…} 属性类:用码点的 Unicode 档案来匹配

字符的编码那页讲了字符的编号(code point)与存储(UTF-16 / UTF-8)。这页讲第三样: 每个编号在 Unicode Character Database (UCD) 里都有一份档案——名字、 General_Category(它是字母 / 数字 / 标点…)、Script(它属于哪套文字)、 外加几十个二元属性(White_Space?Math?…的勾选框)。\p{…} 就是「按档案匹配」: 不必手写 [一-鿿] 这种码位区间,直接说「我要 \p{Script=Han}」。 \P{…} 是取反;两者都必须开 uv 标志—— 没有标志时 \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 672Lu Ll Lt Lm LoA é 中 ٱ 𝑥
\p{M}Mark 标记(组合用)2 543Mn Mc Meé 拆开后的 ◌́
\p{N}Number 数字1 924Nd Nl No7 ٧ Ⅻ ① ½
\p{P}Punctuation 标点856Pc Pd Ps Pe Pi Pf Po, 、 « » _
\p{S}Symbol 符号8 617Sm Sc Sk So+ € ^ 😀
\p{Z}Separator 分隔19Zs Zl Zp空格 NBSP 全角空格
\p{C}Other 其他954 481Cc 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 只能记 CommonScript_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 —— 两份名单高度重合但不相等(每格实时测出):

差异恰好两处:BOM 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。
而且 block 是住址,不是身份——就算能用也常不是你要的:其一 同一个 block 里能住好几套文字 (CJK Symbols and Punctuation 区里的 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)。按码位平面分段, 搜索框支持三种查法:块名(忽略大小写 / 空格 / 连字符,如 superscriptlatin1)、 码点 hex(如 2070U+2070 → 落在哪个 block)、或直接粘一个字符

和别的页串起来:空白与换行页\s 完整清单对应这页的 White_Space 勾选框;emoji 六属性页讲的 \p{Emoji} 一家就是六个二元属性;自研引擎页@vega/parsing/regex 同样支持 gc / sc / scx / 二元属性三种写法、同样不支持 Block—— 名字解析也按 JS 的严格拼写来。