正则小白
经常在工作中用的正则的时候,都是第一时间上网搜索,毕竟这种东西感觉都是别人写的好,正则用到方恨少。 但是其实有的需求,是搜索不到的,需要自己写的。如果不会的话,只能用一些迂回方式,明明一个正则表达式实现, 可是自己偏偏不会。所以,想要学习这方面的知识,刚好在机缘巧合下,看到这本书,感觉基础易懂,跟着书中的例子一步步学习,对正则总算有个大概的认识了,所以看完想跟大家分享自己的学习感悟心得。
匹配单个字符(单个词)
例如文本: my name is ben, hhhhhh, xxxx is ben, just ben,...Ben
- ben就是一个文本正则
- 一般正则, 默认只返回第一个匹配结果
- 返回多个匹配结果需要额外添加条件(g)
/ben/g g代表global - 正则区分大小写的,ben就不能匹配Ben, 可添加i来取消大小写区分限制
/ben/i
const text = 'my name is BEN ben, ben1 ben2 Ben BEn BEN';
const reg = /ben/;
// 翻译为:1. 匹配ben这个文本,2. 区分大小写,3, 如有多个符合ben的文本,只返回最先匹配的文本
const reg1 = /ben/g;
// 翻译为:1. 匹配ben这个文本,2. 区分大小写,3, 如有多个符合ben的文本,全部返回
const reg2 = /ben/i;
// 翻译为:1. 匹配ben这个文本,2. 不区分大小写,3, 如有多个符合ben的文本,只返回最先匹配的文本
console.log(text.match(reg));
console.log(text.match(reg1));
console.log(text.match(reg2));
输出结果如下:
匹配一组字符
看个例子:我们有多个Excel文件,需要查找文件名包含,ale+1个为任意字符的所有xls文件,我们的正则如:
const text = 'sale1.xls sale2.xls sales.xls'
const reg = /ale./g
console.log(text.match(reg));
// 输出结果为[ 'ale1', 'ale2', 'ales' ]
问题:如果我们只想匹配ale+数字的.xls的文件,并不想匹配ale+非数字的.xls文件,该如何写呢?
- 前三个字符肯定是ale,第四个为数字。即ale+0123456789(这个中的任意一个)
- 那正则中,是如何表示0-9任意一个数字可以被匹配呢。这就需要集合
[]来表示了。 - 字符
[](中括号)不匹配任何字符, 代表一个字符集合,表示这个集合的字符都可以被匹配的
那我们的上述的问题,就可以解答了,正则如下:
const text = 'sale1.xls sale2.xls sales.xls'
const reg = /ale[0123456789]/g
console.log(text.match(reg));
// 输出结果:[ 'ale1', 'ale2' ]
此时,我们初步了解了字符集的作用和用法了,下面来看看字符集更加详细的相关知识点吧。
字符集
0123456789这代表一个数字的字符集,如果要表示一个a到z的英文字母匹配字符集,那我们难道要像数字字符集那样,一一列出来嘛,这样多麻烦。此时就需要[-](中横线)[0-9]即代表0123456789, 那么[a-z]就是代表英文a到z的26字母了。[0-9], [a-z]类似这样的写法就称为字符区间。常用的字符区间有:[0-9], [a-z] [A-Z]- 定义的字符区间,必须要有意义,例如
[3-1]这样就没有意义,因为结束的1小于开始3。这样会使正则失效 - 在
[-]字符集合中的中横线一个元字符(待会解释,暂时理解为关键字即可),集合外面,还是代表其本身,就是一个中横线。
const reg = [0-9]; // 匹配0到9的任意一个数字
const reg = /0-9/ // 匹配0 + 中横线 + 9 这三个字符
- 集合取反(取非)使用特殊字
^,[^0-9]就是匹配不包含集合0123456789, 之外的内容, 还是上述那个问题,如果我们只想查找,Excel文件名中包含ale+非数字的文件,那正则就可以这样写:
const reg = /ale[^0-9]/g
元字符
刚才我们提交字符区间里面的[-]的中横线就是一个元字符,那么元字符究竟是什么意思呢。下面我们来看看起定义:
- 在正则表达式中有特殊含义的字符
- 因为字符在正则表达式里有特殊意义,所以字符无法代替本身,必须经过转义,才能代替其本身,用(反斜杠)进行转义,例如
- 转义字符本身--反斜杠(\)
- 英文的点(.)
\.或者\\代表匹配元字符本身的点和反斜杠- 定义字符区间
0-9,a-z,A-z的中横线, 中括号(\-,\[\])都需要转义字符进行转义,才能匹配其本身
配对使用的元字符,不用做元字符的时候,必须使用转义,不然解析不正确,例如:
const text = 'array[0]hhhharray[1]'
const reg = /array\[[0-9]\]/g
const reg1 = /array[[0-9]]/g
console.log('配对的转义字符匹配', text.match(reg))
// 输出 ['array[0]', 'array[1]']
console.log('配对的转义字符匹配', text.match(reg1))
// 输出 null
我们需要array[0],array[1]......因为中括号是元字符,需要匹配其本身的话,就需要转义\[\]
如果不转义的话,就会被认为匹配是一个区间。[[0-9]]区间套区间,解析错误,导致匹配结果为空。
常见的元字符分类
- 匹配空白字符
- 字符类
- 匹配
+,?,*,{}字符出现的次数 - 子表达式
()括号
匹配空白字符
[\b]---匹配backspace键\f---换页符\n---换行符,在window系统空白行使用\n\r, 而unix系统使用\n\n\r---回车\t---制表符(Tab键)\v---垂直制表符
字符类
\d等同于[0-9], 匹配任何一个数字\D等同于[^0-9],匹配任何一个非数字\w等同于[a-zA-z0-9_]匹配任何字母数字以及下划线\W等同于[^a-zA-z0-9_]不匹配任何字母数字以及下划线\s等同于[\f\n\r\t\v]匹配任意空白字符\S等同于[^\f\n\r\t\v]不匹配任意空白字符
**匹配+,?,*,{}字符出现的次数 **
+代表前面的字符,需要出现至少1次以上(可记忆为:加1, 加1的前提,你得有1是吧)?代表前面的字符要么存在,要么不存在(可记忆为:问问问题,要么有结果,要么没结果)*代表前面的字符随意次数(可记忆为:你想出现就出现,出现多少次你随意){}代表前面字符出现的区间,例如:2{3,4}代表匹配222,2222,{开始此次, 结束的次数},如果结束的次数不写的话,代表无限次数即写法为{1,}, 等同于+
例如,我们有这样的一个需求,需要将用户输出的文本,符合test2或者test22(即test文本的数字2),至少需要出现1次,或者多次。替换成替换文案, 我们正则该如何写呢。
const userInputText = 'today is a nice day, test2 nice test2222 nice test';
const reg = /test2+/g
console.log(userInputText.replace(reg, '替换文案'))
// 输出 today is a nice day, 替换文案 nice 替换文案 nice test
// 也可以采用指定出现次数{}的写法
const reg1 = /test2{1,}/g
console.log(userInputText.replace(reg1, '替换文案1'))
// 输出: today is a nice day, 替换文案1 nice 替换文案1 nice test
如果只需要将test或者test2替换成替换文案,又该咋写呢?
const userInputText = 'today is a nice day, test2 nice test2222 nice test';
const reg = /test2?/g
const reg1 = /test2{0,1}/g
console.log(userInputText.replace(reg, '替换文案'))
// 输出:"today is a nice day, 替换文案 nice 替换文案222 nice 替换文案"
console.log(userInputText.replace(reg1, '替换文案1'))
// 输出: "today is a nice day, 替换文案1 nice 替换文案1222 nice 替换文案1"
如果只需要将test22,test222,test2222替换成替换文案咋写呢?
const userInputText = 'today is a nice day, test2 nice test2222 nice test';
const reg = /test2{2,4}/g
console.log(userInputText.replace(reg, '替换文案'))
// 输出:"today is a nice day, test2 nice 替换文案 nice test"
如果需要将test2,数字2出现的次数不限,即test,test2(2可以出现无数次)替换成替换文案咋写呢?
const userInputText = 'today is a nice day, test2 nice test2222 nice test';
const reg = /test2{0,}/g
const reg1 = /test2*/g
console.log(userInputText.replace(reg, '替换文案'))
// 输出: "today is a nice day, 替换文案 nice 替换文案 nice 替换文案"
console.log(userInputText.replace(reg1, '替换文案1'))
// 输出: "today is a nice day, 替换文案1 nice 替换文案1 nice 替换文案1"
写在最后
如有错误,恳请指正。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情