正则表达式(regular expression)是一个描述字符模式的对象。
ECMAScript的RegExp类表示正则表达式。
而string和RegExp都定义了使用正则表达式进行强大的模式匹配和文本检索与替换的函数。
简单的模式可以是一个单独的字符。a
更复杂的模式包括了更多的字符,并可用于解析、格式检查、替换等等。
您可以规定字符串中的检索位置,以及要检索的字符类型,等等。
正则表达式只是一个字符串。没有长度限制,但是,这样的正则表达式长度往往较短。如下所示是一些正则表达式的例子:
I had a \S+ day today
[A-Za-z0-9\-_]{3,16}
\d\d\d\d-\d\d-\d\d
v(\d+)(\.\d+)*
TotalMessages="(.*?)"
]>
这些字符串实际上都是微型计算机程序。
正则表达式的语法,实际上是一种轻量级、简洁、适用于特定领域的编程语言。
var re = /a/
var re = new RegExp(“a”,“修饰符”);
var reg=new RegExp("a","g");
console.log(reg.flags);//修饰符
console.log(reg.source);//正则内容
方法 | 功能 |
---|---|
test() | 返回一个布尔值,方法用于匹配字符串,匹配成功返回true,失败返回false |
exec() | 方法检索字符串中的指定值。返回值是被找到的值。如果没有发现匹配,则返回 null。 |
var reg=/a/g;
console.log(reg.test("abac"));
console.log(reg.test("abac"));
console.log(reg.test("abac"));//false
console.log(reg.test("abac"));//重新从第一个开始查找
注意:
在一个正则对象使用test或者exec时,如果使用全局查找,将自动记录查找指针,同一个正则对象再次查找指针会继续上次的位置开始向后查找
exec 使用全局g无效 一次无法全部找到,多次可以使用全局g
方法 | 功能 |
---|---|
replace() | 用于替换,接受两个参数,第一个是匹配项,第二个可以是字符串或是一个函数 |
match() | 接受一个参数,正则去匹配字符串,如果匹配成功,就返回匹配成功的数组,如果匹配不成功,就返回null |
search() | 参数与match相同,返回字符串中第一个匹配项的索引,没有匹配项返回-1 |
Split() | 把字符串分割为字符串数组。 |
找见某一个字符并换掉
var str="abcdefB";
str=str.replace(/c/,"z");
console.log(str);//abzdefB
全局 从头查找到尾部
str=str.replace(/b|e/g,"z");//(或)全局 从头查找到尾部
console.log(str);
str=str.replace(/b|e/gi,"z");//i 不区分大小写
替换
var str='{"a":1,"b":2,"c":3}';
str=str.replace(/"/g,"'");
console.log(str)
//{'a':1,'b':2,'c':3}
search在使用g时无效
console.log("abacad".search(/a|d/g))
//0
match 查找内容
console.log("abacad".match(/a|d/g));
['a', 'a', 'a', 'd']
可以使用正则表达式多种符号切割字符
console.log("a-b-c".split("-"));//['a', 'b', 'c']
console.log("a=b-c".split(/=|-/));//['a', 'b', 'c']
替换
var str="abacad".replace(/c|d/g,"z");
console.log(str);//abazaz
replace不但可以查找一个,通过正则表达式可以查找多个,也可以替换为不同的内容
var i=0;
var str="abacad".replace(/c|d/g,function(item,index,str){
console.log(item,index,str);
i++;
return i;
})
console.log(str)//aba1a2
var str = "abc345hh67";
var reg = /\d{2}/;
console.log(str.match(reg));//['34', index: 3, input: 'abc345hh67', groups: undefined]
console.log(str.search(reg));//3
console.log(str.replace(reg,"哈哈哈哈"));//abc哈哈哈哈5hh67
修饰符 | 功能 |
---|---|
i | 执行对大小写不敏感的匹配。 |
g | 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。 |
m | 执行多行匹配。 |
正则表达式中包含了一系列的字符,这些字符只能匹配它们本身。有一些被称为“元字符”的特殊字符,可以匹配一些特殊规则。
如下所示的例子中,我用蓝色标出了元字符。
I had a \S+ day today
[A-Za-z0-9\-_]{3,16}
\d\d\d\d-\d\d-\d\d
v(\d+)(\.\d+)*
TotalMessages="(.*?)"
]*>
大部分的字符,包括所有的字母和数字字符,是普通字符。也就意味着,它们只能匹配它们自己。例如:
cat
意味着,只能匹配一个字符串,以“c”开头,然后是字符“a”,紧跟着是字符“t”的字符串
不做特殊说明,正则表达式中是区分大小写的。但是,几乎所有正则表达式的实现,都会提供一个Flag用来控制是否区分大小写。
/c.t/
就是第一个字符是c
,第二个字符是任意字符,第三个字符是t
。注意如果ct
,或者coot
是不符合规则的。/c\.t/
如果用\.
来描述,.在这里就不是通配符了,而是表示第一个字符是c
,第二个字符是.,第三个字符是t
注意:在元字符中.不能用于 匹配换行符,因为换行符在不同的表示方法中实现不同。
只有满足[ ]任意一个字符
字符类是一组在方括号中的字符【a-z】【A-Z】【0-9】
例如
c[aeiou]t
第一个字符是c,第二个字符可以是a,e,i,o,u中的任意一个字符,第三个字符是t。[a]
匹配单一字符a[\[\]\ab]
仅匹配一个字符,[ 意味着匹配“[”,]意味着匹配“]”,\ab,意味着匹配一个a或者b的字符。[\\\[\]]
???这是什么console.log('\\[]'.match(/\\\[\]/));// 输出:['\\[]', index: 0, input: '\\[]', groups: undefined]
console.log('\\[]');// 输出:\[]
[dabaaabcc]
注意这里出现了重复和顺序问题,这种写法其实没有任何意义,与[abcd]相同[.]
这种元字符是匹配.,与.单独出现是不同的。他表示必须匹配一个字符全角字符句号,与单独出现与.的作用也不相同,后者是一个.字符。/[.]/
代表字符. 不是通配符[1-9]
1,2,3,4,5,6,7,8,9[A-Z]
大写的A到Z的所有字符匹配[0-9.,]
匹配0到9的任意数字或者全角句号或者逗号[0-9A-F]
匹配0到9的任意数字或者大写A到大写F的任意字符[0-9a-z\-]
匹配0-9,a-z的任意数组或者字符,或者-字符[]
这种字符类匹配是为了在匹配是某些字符可以是多个字符。所以单独使用[a]
与a
是一样的作用。错误提示
即使[A-z]在你使用的实现中,是合法的,也可能会产生无法预料的运行结果。
[1-31] 这是什么??1,2,3还是1-31。
[1-31] 匹配的是123中的某一项
console.log(/[{}]/);//匹配{ 和 }任意一个字符
[^]反义字符,表示除了^所描述的字符外的其他字符,类似于js中!的作用。
[^a]
[^a-zA-Z0-9]
[\^abc]
[^\^]
项目 | Value |
---|---|
\w | 查找单词字符。与[a-zA-Z_0-9]相同 |
\W | 查找非单词字符。[^0-9A-Za-z_]相同 |
\d | 查找数字。与[0-9]相同 |
\D | 查找非数字字符。与[^0-9]相同 |
\s | 查找空白字符。 |
\S | 查找非空白字符。 |
\b | 单词分割符 |
\B | 非单词分割符 |
用空格切割
console.log("ab cd ef".split(/\s/));//用空格切割
// ['ab', 'cd', 'ef']
用非空格匹配后的字符数组转为字符串
console.log(" aja ajsn asd assd a a sa asd ".match(/\S/g).join(""));
m{n}
表示m重复n次
console.log(/1[3-9]\d\d\d\d\d\d\d\d\d/.test("13890876890"))
console.log(/1[3-9]\d{9}/.test("13890876890"))
console.log(/ab{3}/) //abbb
console.log(/(ab){3}/) //ababab
console.log(/a{1}/)// 等价与/a/
console.log(/a{0}/)// 匹配""字符
console.log(/\d\d\d\d-\d\d-\d\d/)
console.log(/\d{4}(-\d{2}){2}/)
{最低,最多}
console.log("caab".match(/ca{3,8}b/))//null
console.log("caaab".match(/ca{3,8}b/))
console.log("caaaaaaaab".match(/ca{3,8}b/))
console.log("caaaaaaaaab".match(/ca{3,8}b/))//null
console.log("a1231241231b".match(/a\d{1,20}b/));
console.log("a1b".match(/a\d{0,20}b/));//可以是:"ab","a1b";
//任意字符一位或者40位之间
console.log("a1283712387basvad18927318273v".match(/a.{1,40}v/g));//['a1283712387basvad18927318273v']
console.log("aaaaaaaa".match(/a{3,5}/g));// ['aaaaa', 'aaa']
不给最大值,表示无穷大(0个也好,无数也罢)
console.log("aaaaaaaaa".match(/a{0,}/g));//不给最大值,表示无穷大
几种不同的取值情况
console.log("a".match(/a{0,}/g));
//['a', '']
console.log("a".match(/a{0}/g));
//['', '']
console.log("a".match(/a{1}/g));
//['a']
console.log("colour".match(/colou{0,1}r/g));
//可有可无
所以就有了几种简写模式
{0,} _ * | 0个也好,无数也罢 |
---|---|
{1,} _ + | 整一个及以上 |
{0,1} _? | 可有可无 |
在.
字符后面有*?
或者+?
通通称之为非贪婪匹配;
console.log("av1283712387basvad18927318273v".match(/a.+?v/g));
// ['av1283712387basv', 'ad18927318273v']
console.log("av1283712387basvad18927318273v".match(/a.*?v/g));
// ['av', 'asv', 'ad18927318273v']
console.log("中国的四大名著包括《西游记》、《三国演义》、《水浒传》、《红楼梦》".match(/《.+?》/g))
//['《西游记》', '《三国演义》', '《水浒传》', '《红楼梦》']
var str = "Uber的这款无人车原型配备了多个摄像头、激光雷达以及传感器,可看清100米范围内任何方向的东西
第二行内容,哎嘿,第二行内容
";
str=str.replace(/<.+?>/g,function(item){
return item==="
"? "\n" : "";
})
项目 | Value |
---|---|
^ 起始 | 正则表达式开始的位置加入这个表示整个字符串必须以这个字符起始 |
/^a/ | 必须以a作为开始 |
$ 结束 | 正则表达式结束的位置加入这个表示整个字符串必须以这个字符结束 |
/a$/ | 必须以a结束 |
console.log(/^ab$/.test("ab"))//true
console.log(/b.{4}$/.test("asdhjasdbaaaa"));//匹配后几位是b的结尾
|
或者注意:如果这里的写两个||表示对空字符也会做一个匹配
如果匹配成功,不会进行后面正则判断
console.log(/cat|dog/.test("dog"));
console.log(/cat|dog/.test("cat"));
console.log("abacad".match(/ab||ac/g));
console.log("abacad".match(/ab|ac|/g));
console.log("abacad".match(/|ab|ac/g));
true
true
['ab', '', '', '', '', '']
['ab', 'ac', '', '', '']
['', '', '', '', '', '', '']
/a|b/ 等价于 [a|b]
匹配1-31
/^[1-9]$|^[12]\d$|^3[01]$/
匹配0-255
/^\d$|^[1-9]\d$|^1\d{2}$|^2[0-4]\d$|^25[0-5]$/
匹配IP地址
0.0.0.0-255.255.255.255
/^(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])(\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])){3}$/
例如:
var str="3" ;
console.log(str.match(/(\d+)<([a-zA-Z]+)>/))
网址正则
var str="http://www.163.com/news/a/b/index.html";
console.log(str.match(/(https?:)\/\/([^\/]+)(.+\/)(.*)/));
match不允许群组的全局查找
群组の替换
var str="3[ab]12[cd]";
str=str.replace(/(\d+)\[([a-zA-Z]+)\]/g,function(item,a,b){
// console.log(item,a,b);
return b.repeat(a);
});
console.log(str)
//abababcdcd
群组替换,对象赋值
var str="a=3&b=a&c=5&d=6";
var o={};
str.replace(/(\w+)=([^&]+)/g,function(item,a,b){
o[a]=isNaN(b) ? b : Number(b);
})
console.log(o)
群组替换
var str="18617890567";
// 群组1 $1
// 群组2 $2
str=str.replace(/(\d{3})\d{4}(\d{4})/,"$1****$2");
console.log(str);
186****0567
var str="11012219980524401X";
str=str.replace(/(\d{4})\d{11}(\d{3}|\d{2}X)/,"$1***********$2");
console.log(str);
1101***********01X
var str="3[2[a]3[bc]]2[ab]";
function stringify(str){
if(!/\d+\[\w+\]/.test(str)) return str;
return stringify(str.replace(/(\d+)\[(\w+)\]/g,function(item,a,b){
return b.repeat(a);
}));
}
str= stringify(str);
console.log(str)
aabcbcbcaabcbcbcaabcbcbcabab
后置肯定断言?=n
判断a的后面是不是d,如果是则替换这个a
var str="abadae";
console.log(str.replace(/a(?=d)/g,"0"));
//ab0dae
后置否定断言 ?!n
判断a的后面是除了d的a之外的所有a被替换
var str="abadae";
console.log(str.replace(/a(?!d)/g,"0"));
//0bad0e
前置肯定断言 ?<=n
看箭头指向,b的前面是c的这样的b,被替换
var str="abcbdb";
console.log(str.replace(/(?<=c)b/g,"0"))
//abc0db
前置否定断言 ?
判断b前面是除了c的a之外的所有b被替换0
var str="abcbdb";
console.log(str.replace(/(?/g,"0"))
a0cbd0
"3+5="-->"3+5=8"
面试题var str="1+2+3=";
str=str.replace(/(?<=\=)/,function(item,index,str){
return str.match(/(\d+)\+(\d+)\+(\d+)/).slice(1).reduce(function(v,t){
return Number(v)+Number(t);
})
})
console.log(str);
(?=\D+\d) 起始字符开始首字母不能是数字,但是在整个字符串中必须包含数字
(?=.*[a-z]) 在任意位置包含a-z的小写字母
(?=.*[A-Z]) 在任意位置包含A-Z的大写字母
[a-zA-Z0-9_-$&!]{8,16} 密码实际包含的字符,要求最少8位,最大16位
/^(?=\D+\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9_\-$&!]{8,16}$/
console.log(/^(?=\D+\d)(?=.*[a-z])[a-zA-Z0-9_\-$&!]{8,16}$|^(?=\D+\d)(?=.*[A-Z])[a-zA-Z0-9_\-$&!]{8,16}$|^(?=.*[A-Z])(?=.*[a-z])[a-zA-Z0-9_\-$&!]{8,16}$/.test("xietian12"))
console.log(/^\d{8,16}$|^[a-z]{8,16}$|^[A-Z]{8,16}$/.test("xietianabc"))
(n)\1* 不重复也可以查找到
(n)\1+ 至少重复1次以上的可以查找到
n就是正则内容
输出字符的个数面试题
var str="hjhjds jksjsdkj alkjd jksdj kswdjli qwdo qijd aksijdais asdiuaiusd asdiuasdkjh";
var o=str.split("").sort().join("").match(/(.)\1*/g).reduce(function(v,t){
// console.log(t,t[0],t.length);
v[t[0]]=t.length;
return v;
},{});
console.log(o)
5、变量 (?<变量>筛选的字符)
把筛选出来的给变量
var str="3[ab]";
var reg=/(?\d+)\[(?\w+)\] /g;
console.log(str.match(/(?\d+)\[(?\w+)\] /).groups)
//{num: '3', str: 'ab'}
str.replace(/(?\d+)\[(?\w+)\] /,function(item,a,b,index,str,groups){
console.log(groups)
})
//{num: '3', str: 'ab'}
<div class="div1 div2 div3"></div>
========================================
function addClass(elem,className){
elem.className=className.match(/\S+/g).reduce(function(v,t){
if(!v.includes(t)) v.push(t);
return v;
},elem.className.match(/\S+/g)).join(" ")
}
var div=document.querySelector("div");
addClass(div," div2 div4 div5 ")
function addClass(elem,className){
elem.className=className.match(/\S+/g).reduce(function(v,t){
if(!v.includes(t)) v.push(t);
return v;
if(v.includes(t)) v.splice(t);//暂存
},elem.className.match(/\S+/g)).join(" ")
}
var div=document.querySelector("div");
addClass(div," div2 div4 div5 ")
中文匹配
/[\u4e00-\u9fd5]{2,4}/