piapia123
zh

glob 通配符测试

网络

所有处理都在浏览器本地完成,数据不上传服务器

输入
把文件拖到这里可直接载入
输出

glob(`*` `?` `[abc]` 与双星号)看起来简单到「谁会写错」,但它有三套互不兼容的方言,同一份模式在 shell、`.gitignore`、`.dockerignore` 里对同一个路径的结论可能不同:前导 `/` 在 shell 里只是普通字符、在那两套里是「锚定到根」;不含 `/` 的模式在 shell 里只匹配当前层、在 gitignore 里匹配任意层(`node_modules` 要能命中 `packages/app/node_modules`,漏掉这条绝大多数 .gitignore 会静默失效);`!` 在 shell 里与匹配无关、在那两套里是取反。 所以这里把方言做成显式选项,并且把模式翻译成的正则一起显示出来 —— 你去核对别人的实现时,看的是同一个东西,而不是靠猜。 ⚠️ 最容易犯的错是把模式直接塞进 `new RegExp`:glob 里的 `.` 是普通字符(正则里是「任意一个字符」),glob 里的 `?` 才是「任意一个字符」(正则里 `?` 是量词)。那样得到的匹配器看起来正常,语义却完全不同。这个工具按 glob 的语义转义。

功能

  • 三种方言分开处理:双星号、前导 `/`、结尾 `/`、`!` 的语义各按各的规矩
  • 逐行给出匹配结论,命中的一行标绿
  • 把模式翻译成正则一起显示,方便核对别的实现
  • gitignore / dockerignore 里取反的模式会单独标出来(它命中时表示「不要忽略」)
  • 字符组 `[0-9]` 与取反 `[!0-9]` 都支持;没闭合的 `[` 当普通字符处理,不会抛正则错误
  • 正则元字符(`.` `+` `(`)按普通字符转义 —— `*.js` 不会匹配 `aXjs`
  • `a/` 后接双星号能匹配 `a` 本身;以双星号开头的模式能匹配根目录下的 `a.ts`
  • 大小写敏感可以关掉

使用方法

  1. 第一行写模式,从第二行起每行一个路径
  2. 按你在核对的东西选方言(本地 shell、.gitignore、.dockerignore)
  3. 看逐行的结论;对不上的那一行再看上面的正则
  4. 改模式时结果实时更新

常见问题

为什么 `*.js` 匹配不到 `src/a.js`?
因为在 shell 的约定里 `*` 不跨路径分隔符,`*.js` 只匹配当前目录下的 .js 文件。要跨目录得写「双星号 + 斜杠 + `*.js`」,或者 `src/*.js`。这一点与「正则里的 `*`」很容易混:正则的 `.*` 默认跨一切,glob 的 `*` 不跨 `/` —— 这也是 glob 转正则时最容易写成 `.*` 的一处。
以双星号开头的模式为什么能匹配到根目录的 `a.ts`?
因为「双星号 + 斜杠」这一段是「任意层目录,包括零层」。写这种模式的人想要的是「所有 .ts 文件」,而根目录下的文件显然也算,所以那一段必须可以整个不存在。很多手写的实现漏了这条,表现是「粘贴进去一试,src 里的文件都对,根目录的文件全不对」。
`.gitignore` 里的 `!` 是什么意思?
取反:前面刚忽略掉的东西,被 `!` 这一条重新包含回来。所以一条取反规则命中时表示「不要忽略它」,而不是「忽略它」—— 语义与其它规则是反的,这里会单独标出来,免得看结论时读反。注意 shell 里的 `!` 完全不同(历史扩展),与匹配无关,所以切到 shell 方言时它只是一个普通字符。
能拿它逐行验证一份 .gitignore 吗?
可以,但一次一条模式:第一行放要核对的那条规则,下面把相关的路径列出来。整份文件一起贴是不行的 —— 这个工具只按第一行当作模式。要整体验证的话,把有疑问的那几条挑出来分别跑一遍,比整份文件里找一个「为什么这个文件没被忽略」快得多。

相关工具