你不知道的正则表达式之断言
JyLie 2022-02-23 RegExp
# 前言
今天在瞎搞 vue3 重构时用到了require.content
,在使用require.content
的时候用到了正则匹配文件路径的情景,于是重新回顾了一遍 JavaScript 正则匹配相关的内容。本次文章主要针对正则匹配的断言展开,面向在特殊情景下需要排除某个特定长度字段进行匹配。
# 基本概念
正则的断言离不开两个主要概念:
- 前瞻
- 后瞻
前瞻 有分为 正向前瞻 和 负向前瞻。通俗讲为,以特定字符为基准往后匹配特定字符(串)。
后瞻 有分为 正向后瞻 和 负向后瞻。通俗讲为,以特定字符为基准往前匹配特定字符(串)。
前瞻、后瞻一览表,如下:
表达式 | 名称 | 描述 |
---|---|---|
(?=exp) | 正向前瞻 | 匹配后面满足表达式 exp 的位置 |
(?!exp) | 负向前瞻 | 匹配后面不满足(排除)表达式 exp 的位置 |
(?<=exp) | 正向后瞻 | 匹配后面满足表达式 exp 的位置 |
(?<!exp) | 负向后瞻 | 匹配后面不满足(排除)表达式 exp 的位置 |
通过上述表格基本可以理解前瞻与后瞻的用途,主要用于匹配字符的位置。当然可以根据自身需求来判断是匹配满足(排除)某字符后面的字符(串),还是满足(排除)某字符前面的字符(串)。
# 情景交融
# 基础案例
// 以Jy为基准往后看,是否紧跟着Lie字段
/Jy(?=Lie)/g.test('JyLie')
// 以Jy为基准往后看,是否不紧跟着Lie字段
/Jy(?!Lie)/g.test('JyLie')
// 以Jy为基准往前看,是否紧跟着Lie字段
/(?<=Lie)Jy/g.test('LieJy')
// 以Jy为基准往前看,是否不紧跟着Lie字段
/(?<!Lie)Jy/g.test('LieJy')
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# require.content
匹配文件
在 node.js 中常使用到 require.content
动态获取文件,Frontender 在开发过程中也常有使用,如 vue.js 中常用 require.content
来动态获取当前目录下的文件,免得每次手动引入的麻烦,于是一顿操作猛如虎~
/*
目录结构:
|--languages
|----en.ts 英文字段
|----zh.ts 中文字段
|----index.ts 使用require.content整合字段,本文将不需被引用
*/
export default function loadLanguages() {
const files = require.content('./', false, /(?<!index)\.ts$/);
const language = files.keys().reduce((acc, key) => {
const name = key.replace(/(.*\/)*([_-\w]+)(\.ts)*$/, '$2') || '',
message = files(key).default;
acc[name] = message;
return acc;
}, {});
}
loadLanguages(); // 获取所有语言的字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
可见通过/(?<!index)\.ts$/
即可排除index.ts
的引用,؏؏☝ᖗ 乛 ◡ 乛 ᖘ☝؏؏
# 查找以某字符开头的字符串
/^(?=JyLie).*$/.test('JyLie, Haha'); // true
1
# 查找不以某字符开头的字符串
/^(?!JyLie).*$/.test('Haha,JyLie'); // true
1
# 查找以某字符结尾的字符串
/^.*(?<=JyLie)$/.test('Haha, JyLie'); // true
1
# 查找不以某字符结尾的字符串
/^.*(?<!JyLie)$/.test('JyLie, Haha'); // true
1
# 查找不包含某个字符的字符串
/^(?!.*JyLie).*$/.test('hahah, JyLie, Haha'); // false
/^(?!.*JyLie).*$/.test('JyLie, Haha'); // false
/^(?!.*JyLie).*$/.test('hahah, JyLie'); // false
1
2
3
2
3
# 查找指定字符之间不包含某个字符的字符串
/A((?!JyLie).)+A/.test('hahah, JyLie, Haha '); // false
/A((?!JyLie).)+A/.test('A hahah, JyLie, Haha A'); // false
/A((?!JyLie).)+A/.test('A hahah, LieJy, Haha A'); // true
1
2
3
2
3
# 结语
总的来讲,正则的断言就是要抓住以谁为基准对字符串做匹配,是以特定字符为基准往后匹配特定字符串呢,还是以特定字符为基准往前匹配特定字符串,搞清楚基准问题一切好办。
啊哈哈哈哈嗝,刚加了个班总结文章,一眨眼就到 8 点半,是该归巢洗洗睡啦~