* / ? / [...]:一段之内怎么配
glob 把路径看成用 / 隔开的一串段 (segment),三个基础通配符全都只在一段之内生效:* 匹配零个或多个字符、? 匹配恰好一个、[...] 匹配集合里的一个。它们谁都不会越过 /——这是 glob 与正则最大的行为差异,也是「为什么 *.js 配不到子目录」的答案。
下面的匹配器里特意混了一个带路径的 lib/util.js 和一个 dotfile .eslintrc.js。试 *.js:三个根级 js 命中,这两个都不命中——前者受限于「* 不跨 /」,后者受限于 dot 规则(04 页细讲)。匹配由本仓库实现 @vega/parsing/glob 的 matchGlob 执行。
1 · *:零个或多个,但有两条限制
* 是最宽容的通配:*.js 里它可以是 app、也可以是空串(所以 *.js 命中只有扩展名的文件名 .js 吗?——不,空串开头违反 dot 规则,见 04 页;但 a*.js 命中
a.js,这里 * 匹配的就是空串)。它的两条限制:不跨 /——跨目录要用 02 页的 **; 不匹配开头的 .——dotfile 要显式写点。
2 · ?:恰好一个,不多不少
? 与正则的 ? 是假朋友 (false friend):正则里它表示「前面那个元素可有可无」,glob 里它自己就是「任意一个字符」(相当于正则的 .,只是不含 /)。所以 file?.txt 命中
file1.txt、filea.txt,却不命中 file10.txt——10 是两个字符。连用即计数:*.?? = 扩展名恰好两个字符。
3 · [...]:从集合里挑一个
[0-9]、[abc]、[a-zA-Z] 与正则字符类同款;否定写 [!0-9](bash 传统,多数实现也兼容正则风格的 [^0-9],本仓库实现两种都认)。想匹配字面的 [ 或 ],套一个单字符集合:[[] 匹配
[、[]] 匹配 ];或者用反斜杠转义 \[(注意 Windows 上反斜杠是路径分隔符,见 06 页的易错点清单)。
为什么「不跨 /」是好设计? glob 的使用场景是「圈一批文件」,目录层级正是最需要精确控制的维度。src/*.ts 读作「src 直接底下的 ts 文件」,语义干脆;要「不限深度」时再显式升级成 src/**/*.ts。如果
* 默认跨段,这两种意图就无法区分了。