前言:正则表达式(regular expression)反反复复学了多次,学了又忘,忘了又学,这次打算把基本的东西都整理出来,加强记忆,也方便下次查询。
学习正则表达式之前首先需要掌握记忆这些基本概念:
1.元字符:(.,\w,\W,\d,\D,\s,/S,^,$,)
字符 | 含义 |
---|---|
. | 匹配除了换行符以外的任意字符。 |
\s | 代表任意空白符(换行符,制表符,空格) |
\S | 匹配任意非空字符串 |
\b | 匹配单词边界,匹配单词的开头和结尾。 |
\B | 匹配一个非单词边界 |
\d | 匹配一个数字,等价于[0-9] |
\D | 匹配一个数字,等价于[^0-9] |
\w | 匹配一个单字字符(字母、数字或者下划线)等价于[A-Za-z0-9_],例如, /\w/ 匹配 "apple," 中的 'a',"$5.28,"中的 '5' 和 "3D." 中的 '3'。 \W匹配一个非单字字符。等价于[^A-Za-z0-9_],例如, /\W/ 或者 /[^A-Za-z0-9_]/ 匹配 "50%." 中的 '%'。 |
\W | 匹配一个非单字字符。等价于[^A-Za-z0-9_],例如, /\W/ 或者 /[^A-Za-z0-9_]/ 匹配 "50%." 中的 '%'。 |
^ | 匹配字符串的开始用在[]括号里面表示排除,/^A/ 并不会匹配 "an A" 中的 'A',但是会匹配 "An E" 中的 'A'。 |
$ | 匹配字符串的结束。例如,/t$/ 并不会匹配 "eater" 中的 't',但是会匹配 "eat" 中的 't'。 QQ号必须为5位到12位数字时,可以使用:^\d{5,12}$ |
我们发现\W加大写字母都是表示相反的意思。
2.分组符([],(),{});
字符 | 含义 |
---|---|
() | 如果想要重复多个字符该怎么办?你可以用小括号来指定子表达式(也叫做分组),然后你就可以指定这个子表达式的重复次数了。eg: (\d{1,3}\.){3}\d{1,3}是一个简单的IP地址匹配表达式。要理解这个表达式,请按下列顺序分析它:\d{1,3}匹配1到3位的数字,(\d{1,3}\.){3}匹配三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个一到三位的数字(\d{1,3})。 |
[] | 代表一个字符集合。匹配方括号的中任意字符,包括转义序列。你可以使用破折号(-)来指定一个字符范围。对于点(.)和星号(*)这样的特殊符号在一个字符集中没有特殊的意义。他们不必进行转义,不过转义也是起作用的。例如,[abcd] 和[a-d]是一样的。他们都匹配"brisket"中得‘b’,也都匹配“city”中的‘c’。/[a-z.]+/ 和/[\w.]+/都匹配“test.i.ng”中得所有字符。 |
{} | 表示量词的范围的。 |
3.修饰符(i,g,m);
字符 | 含义 |
---|---|
i | 忽略大小写 |
g | 执行全局匹配 |
m | 执行多行匹配 |
4.量词(*,?,+,-,{n,m},?=n,?!=n);
字符 | 含义 |
---|---|
* | 匹配任意次,.*连在一起就意味着任意数量的不包含换行的字符。等价于{0,} |
+ | 匹配前面一个表达式1次或者多次。等价于 {1,}。 |
? | 匹配前面一个表达式0次或者1次。等价于 {0,1}。 |
{n,m} | 匹配n到m次 |
x(?=y) | 匹配'x'仅仅当'x'后面跟着'y'.这种叫做正向肯定查找。 例如,/Jack(?=Sprat)/会匹配到'Jack'仅仅当它后面跟着'Sprat'。/Jack(?=Sprat|Frost)/匹配‘Jack’仅仅当它后面跟着'Sprat'或者是‘Frost’。但是‘Sprat’和‘Frost’都不是匹配结果的一部分。 |
x(?!y) | 匹配'x'仅仅当'x'后面不跟着'y',这个叫做正向否定查找。 例如,/\d+(?!\.)/匹配一个数字仅仅当这个数字后面没有跟小数点的时候。正则表达式/\d+(?!\.)/.exec("3.141")匹配‘141’但是不是‘3.141’ |
实例解析:
var reg = /\(?0\d{2}[) -]?\d{8}/。
“(”和“)”也是元字符,后面的分组节里会提到,所以在这里需要使用转义。
这个表达式可以匹配几种格式的电话号码,像(010)88886666,或022-22334455,或02912345678等。我们对它进行一些分析吧:首先是一个转义字符\(,它能出现0次或1次(?),然后是一个0,后面跟着2个数字(\d{2}),然后是)或-或空格中的一个,它出现1次或不出现(?),最后是8个数字(\d{8})。
以下通过实例来讲解RegExp:
需求一:在一句话英文中匹配一个hi的单词。
var str = 'Hi RegExp I love you so much Hi Hi hi';
var reg = new RegExp("\\bhi\\b","gi");//g是一个修饰符,表示全局匹配。\b是一个元字符,代表单词边界,匹配单词的开头和结尾。
//直接量语法:
reg2 = /\bhi\b/gi;
console.log(str.match(reg2));//['hi','hi','hi','hi']
//升级
//匹配hi后面不远处跟着一个lucy
var strlc = /\bhi\b.*\blucy\b/;
var luch = 'hi welcome to beijing lucy!!!';
console.log(luch.match(strlc));
需求二:在一句话英文中匹配一个hi的单词。
var reg = /0\d\d\d-\d\d\d\d\d\d\d\d/;//\d代表一个数字,等价于[0-9],\D匹配一个非数字字符,等价于[^0-9]
var tel = "0123-887523146";
console.log(tel.match(reg));//0123-88752314;
//这个连续写多次的方法很笨哎,所以引进了变量。
regTel = /0\d{3}-\d{8}/;
console.log(tel.match(regTel));//0123-88752314;
需求三:写一个清除字符串前后空格的正则表达式。
String.prototype.trim = function(){return this.replace(/(^\s*)|(\s*$)/g, "");}
var str2 = " hi space "//这里前后共有两个空格
console.log(str2.length);//14
console.log(str2.trim().length);//8
console.log(str2.trim());//hi space
需求四:匹配一个邮箱。
var eReg = /\S*@\S*\.\S*/;
console.log(eReg.test('873619879@qq.com'))//true
更多实战用法
// match的用法使用分组,且不使用g全局匹配 // 语义: 找出首次匹配等号前后都是英文字母的字符串, 并返回分组内匹配的字符串。 var str = '2019shanghai=nihao !! my_age=age18' console.log(str.match(/([A-Za-z]*)(=)[A-Za-z]+/)) //下面是返回的结果 /*[ 'shanghai=nihao', 'shanghai', '=', index: 4, input: '2019shanghai=nihao !! my_age=age18', groups: undefined ] */ const reg = /(jack)=([^&]*)/gi const str2 = 'Jack=gggg&Sprat=456' console.log(str2.match(reg)) /* [ 'Jack=gggg', 'Jack', 'gggg', index: 0, input: 'Jack=gggg&Sprat=456', groups: undefined ] */ // 当一件事件你不知道做的时候,就将他们一个个分解,然后各个击破,先写出基本的,再去想办法怎么优化提升性能,缩减代码量之类 // 如何使用正则匹配一个不包含某一个字符的结果 const reg2 = /([^g]*)(.*)/ const str3 = 'yes you has do a good job' console.log(str3.match(reg2)) /* [ 'yes you has do a good job', 'yes you has do a ', 'good job', index: 0, input: 'yes you has do a good job', groups: undefined ] */ // 正则表达式的使用,转化时间的格式 const date = '2020-02-07' const regd = /(\d{4})-(\d{2})-(\d{2})/ const newDate = date.replace(regd, '$1/$2/$3') console.log(newDate)//2020/02/07 //实例三 var ary = ['一', '二', '三', '四', '五', '六'] const newAry = '123456'.replace(/\d/g, function(i) { return ary[i - 1] }) console.log(newAry)//一二三四五六 //获取url的参数 function getQueryString(url, key) { const reg = new RegExp('(.*[?|&])' + key + '=([^&]*)(&|$)')// 点金之笔就在于([^&]*)一次就精准匹配出来了,比起上面的方法少了很多代码量 var r = url.match(reg) if (r != null) return unescape(r[2]) return null } // x(?=y)的用法,匹配x后面是否跟着y,返回x的值 const reg3 = /Jack(?=Sprat)/ const str4 = 'JackSprat' console.log(str4.match(reg3)) /* [ 'Jack', index: 0, input: 'JackSprat', groups: undefined ] */ // x(?!y),匹配x,当x后面不跟着y const reg4 = /\d{3}(?!\.)/ const str5 = '3.145' console.log(str5.match(reg4)) /* [ '145', index: 2, input: '3.145', groups: undefined ] */
参考文章: