javascript正则表达式

JavaScript正则表达式

正则表达式是一种非常强大的用来匹配和处理文本字符串的语言。想要掌握它,是一件非常不容易的事,需要经过长期的实践与磨练。

1、以字面量的方式来创建一个模式,非常简单。

var reg = /name/;

也可以使用构造函数的方式创建一个模式。

var reg = new RegExp(name);

2、test方法

测试一个模式可以使用test方法。匹配成功返回true,匹配失败返回false。

var reg = /name/;
var result = reg.test("name");
console.log(result); //true

test接受一个字符串"name",与模式/name/进行匹配,模式中可包含文本,模式中的name与字符串中的name相匹配,返回true,否则返回false。

var str = "name";
var reg = new RegExp(str);
var result = reg.test("name");
console.log(result); //true

如上,如果需要使用变量,可以使用构造函数形式。

3、match方法与g标志(全局模式)
使用exec方法进行字符串与模式的匹配,可返回一个或多个匹配到的值。

var reg = /name/;
var result = "name age name".match(reg);
console.log(result); //[name]

match接受一个匹配模式作为参数,结果中只返回第一个匹配到的name值。这时候,使用g符号可以开启全局模式,返回所有匹配的结果。

var reg = /name/g;
var result = "name age name".match(reg);
console.log(result); //[name,name]

4、i标志(区分大小写)
正则的匹配过程是区分大小写的,所以name与Name不匹配。想要忽略大小写的限制,可以使用i标志。

var reg = /name/;
var result = "Name age Name".match(reg);
console.log(result); //null 区分大小写

var reg = /name/i;
var result = "Name age Name".match(reg);
console.log(result); //[Name] 不区分大小写

var reg = /name/gi;
var result = "Name age Name".match(reg);
console.log(result); //[Name,Name] 全局模式 + 不区分大小写

5、"."符号 (动态匹配任意字符)
使用英文的句号 “.” ,可以动态匹配任意一个字符。

var reg = /name./;
var result = "name1".match(reg); //name1
var result = "name?".match(reg); //name?
var result = "namesdfdf".match(reg); //names

var reg = /nam.e/;
var result = "nam1e".match(reg); //nam1e
var result = "nam12e".match(reg); //null	

var reg = /name.../g;
var result = "name123".match(reg);//name123

var reg = /.n.a.m.e./g;
var result = "1n2a3m4e5".match(reg);//1n2a3m4e5

英文的句号标号代表一个任意的字符,不论是字符,数字,标点符号都是有效的,只要字符串中包含了这个模式,即使只是部分匹配了,也能够返回匹配到的部分的值。使用test方法的话,将返回true。

温馨提示:我们说".“可以匹配任何一个字符,这个说法并非绝对正确,在绝大多数的正则实现中,”."只能匹配除换行符以外的字符。

6、反斜杠转义符号"/" (匹配特殊字符)
上面我知道,符号 “.” 可以表示任意一个字符,但问题是,如果我们需要在一个字符串中搜索的仅仅是一个英文句号".",不希望这个符号带有什么特殊含义,那该怎么办呢?这时候,可以使用反斜杆"/"来对一些特殊字符进行转义。

var reg = /name./
var result = "name1".match(reg);//name1

//原意是,我们希望模式中的.仅仅是一个英文句号,而不是代表任意一个字符

var reg = /name\./; //我们对.符号使用反斜杆进行转义
var result = "name1".match(reg);//null
var result = "name.".match(reg);//name.

如果需要对反斜杠进行转义,只需在反斜杠的后面再加个反斜杆即可

var reg = /na\\me/; //我们对.符号进行转义
var result = "na\\me".match(reg);//na\me

像"."这样的特殊符号还有很多,这样带有特殊意义的符号有个名字叫做元字符,我们都可以使用反斜杠对特殊符号进行转义。

7、使用[ ]中括号,匹配多个字符中的某一个字符。

var reg = /[jk]name/; 
var result = "jname".match(reg);//jname
var result = "kname".match(reg);//kname
var result = "jkname".match(reg);//kname
var result = "1name".match(reg);//null

在中括号内,可以填写多个任意字符,只要中括号内的其中一个字符与字符串相匹配,就能返回匹配到的值。

8、使用字符区间
我们可以使用字符区间,来限定匹配字符的范围。
[0-9] 表示匹配0-9的数字
[1-3] 表示匹配1-3的数字
[a-z] 表示匹配a-z的字母
[A-Z] 表示匹配a-z的大写字母
[b-d] 表示匹配b-d的字母
[A-Z0-9] 组合模式,表示匹配A-Z和0-9的字符

var reg = /[0-9]name/;
var result = "1name".match(reg);//1name

这里只会匹配0-9的字符。

使用^字符进行取非匹配
[^0-9] 表示匹配除了0-9之外的字符

var reg = /[^0-9]name/; //\D表示排除0-9的数字
var result = "1name".match(reg);//null
var result = "kname".match(reg);//kname

除了0-9之外的字符都可以被匹配到哦

9、匹配空白字符
[\b] 退格符
\f 换页符
\n 换行符
\r 回车符
\t 制表符
\v 垂直制表符

var result = `kname
dsfsdf`.replace(/\n/,"");//knamedsfsdf

上面的模式中,我们匹配了换行符然后替换成空字符。

10、类元字符
类元字符其实就是代表某一类的字符,使用它们,就不必输入一大串字符。
\d 代表任何一个数字字符
\D 代表任何一个非数字字符
\w 代表任何一个字母与数字字符,大小写均可,或下划线字符。
\W 代表任何一个非字母与数字字符,或下划线字符。
\s 代表任何一个空白字符,如换页符,换行符,回车符,制表符,垂直制表符。
\S 代表任何一个非空白字符。

var reg = /\d/g; 
var result = "2s3s4324".match(reg);//[2", "3", "4", "3", "2", "4"]

\d 代表任何一个数字字符,这样我们就不需要输入像123456789这样一长串字符。

11、"+"字符重复匹配一个或多个字符

var reg = /\d/; 
var result = "123456".match(reg);//1

这里\d代表的是匹配0-9的数字,但与1进行匹配了之后,就不再进行匹配了。所以返回值中只有1

var reg = /\d+/; 
var result = "123456".match(reg);//123456

使用+符号之后,会重复匹配多次。所以返回了123456,想要重复匹配某个字符,就在这个字符后面跟上一个+号。
\d表示重复匹配一个或多个字符,不匹配0个的情况。
注意,如果需要对字符集合进行重复多次匹配,应当这样写[0-9]+,而不是[0-9+],在中括号中使用.号或者+号,会被当做普通的文本。
不带任何特殊意义,所以不要进行转义,当然转义了也没什么区别。

var reg = /sdf[.+]/; 
var result = "sdf.+".match(reg);//sdf.

中括号中的.号和+号被当做普通文本字符来对待。

12、(*)元字符重复匹配0个或多个字符

与+号元字符不同的是,+号元字符是至少需要匹配一次。才算成功。
而*号元字符是0次或多次,也就是即使没有被匹配到,也算成功。

var reg = /s+/; 
var result = reg.test("s"); //true 

var reg = /s+/; 
var result = reg.test("d"); //s字符没有出现,返回false。

var reg = /s*/; 
var result = reg.test("s"); //true

var reg = /s*/; 
var result = reg.test("d"); //s字符没有出现,仍返回true。

可以认识到,在*元字符前面的字符是可有可无的。

13、?号元字符,匹配一个字符的0次或1次出现。

var reg = /https?/; 
var result = "httpss?".match(reg);//https

14、{}元字符,限定字符出现的次数

var reg = /https{1}?/; 
var result = reg.test("http"); //false
var result = reg.test("https"); //true
var result = reg.test("httpss"); //true

{}中的数值表示前面的字符至少出现的最少次数,小于指定的次数,将匹配失败。

也可以设定一个区间。

var reg = /https{1,2}/; 
var result = "httpssssss".match(reg);//httpss
var result = "http".match(reg);//null

{}中的1,2表示最少出现一次,最多出现2次。

{}也可以指定至少重复多少次。

var reg = /https{1,}/; 
var result = "http".match(reg);//null
var result = "https".match(reg);//"https"
var result = "httpsss".match(reg);//"httpsss"

var reg = /https{1}/; 
var result = "httpsss".match(reg);//"https"

{1,}代表的是至少重复1次,如果省略逗号,则代表的是至少重复一次,没有更多。

15、贪婪型元字符与懒惰型元字符

var reg = /<b>.*<\/b>/; 
var result = "<b>j</b><b>k</b>".match(reg); //<b>j</b><b>k</b>

或许你会认为匹配的结果是这样的:j, 这是因为*元字符, +元字符, {}元字符都是贪婪型的元字符。
但遇到结束的标记时,没有选择停止,而是继续匹配,它会尽可能地一直匹配到字符串的末尾,并在末尾处找到了第二个匹配的标签。
如果不需要这种贪婪行为,可以把元字符转为懒惰型的版本,只需在元字符后面加?号即可。

var reg = /<b>.*?<\/b>/; 
var result = "<b>j</b><b>k</b>".match(reg); //<b>j</b>

这样一来,当遇到第一个匹配的结束标签时就停止了。

var reg = /<b>.*?<\/b>/g; 
var result = "<b>j</b><b>k</b>".match(reg); //[<b>j</b>,<b>k</b>]

16、^与$元字符 首匹配与尾匹配

如何判断’111abc’和’abc111’这连个字符串当中哪个是以abc开头的呢?

var reg = /^abc/;
var result = reg.test('111abc'); //false
var result = reg.test('abc111'); //true

^元字符表示匹配一个字符串的开头位置。所以如果开头位置不是abc,将不匹配。

反过来,$元字符代表匹配一个字符串的结束位置。比如我们需要知道哪个字符串是以abc结尾的。

var reg = /abc$/;
var result = reg.test('111abc'); //true
var result = reg.test('abc111'); //false

需要注意的是,当你把放在[]内部,如[123],那么^代表的是取非的意思,即排除123之外的字符。

17、m修饰符 配合$和^进行多行匹配。
在默认状态下,一个字符串无论是否有换行都只有一个开头位置和一个结束位置,但使用多行匹配模式的话,每一行都可以有一个开始和结束位置。
默认状态下:
(开始位置)sdf
abc(结束位置)

多行匹配模式下
(开始位置)sdf(结束位置)
(开始位置)abc(结束位置)

var reg = /^NBA/;
var str = `
NBA111
aaa111
NBA111
aaa111
`;
var result = str.replace(reg, 'CBA'); 

结果:
NBA111
aaa111
NBA111
aaa111

这里的需求是找出所有NBA开头的字符,替换为CBA,但结果并没有任何改变。
这是因为默认情况下,只匹配到了第一行,而第一行是空的。第二行至第5行则不进行匹配。
这时候,使用m修饰符就能够进行多行匹配。

var reg = /^NBA/m;
var str = `
NBA111
aaa111
NBA111
aaa111
`;
var result = str.replace(reg, 'CBA'); 

结果:
CBA111
aaa111
NBA111
aaa111

开启多行匹配模式之后,第二行有了变化。由于一般情况下,匹配到了第一个结果后,就不停止匹配了。
所以我们可以开启全局模式,找到所有匹配的结果。

var reg = /^NBA/mg;
var str = `
NBA111
aaa111
NBA111
aaa111
`;
var result = str.replace(reg, 'CBA'); 

结果:
CBA111
aaa111
CBA111
aaa111

18、使用括号()进行分组

括号的作用是能够将模式中的某一部分当做一个整体。

var reg = /hello{2}/; //这里的+号元字符只作用于前面的一个字符,即o身上,代表的是hello中的o至少出现2次。
var reg = /(hello){2}/; //当给hello加上括号后,+号元字符将作用于hello这个整体上,而不只是o身上。它代表的是hello这个字符至少出现2次。

例子一:

var reg = /hello{2}/;
var result = reg.test('helloo')//true

var reg = /(hello){2}/;
var result = reg.test('helloo')//false

var reg = /(hello){2}/;
var result = reg.test('hellohello')//true

例子二:
匹配一个ip地址,如:12.231.23.200

方式一:

var reg = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/;
var result = reg.test('123.231.23.200')//true

方式二:

var reg = /(\d{1,3}\.){3}\d{1,3}/;
var result = reg.test('123.231.23.200')//true

第二种方式把\d{1,3}.放进了括号里,成为一个整体,并且它必须至少重复三次。
至于为什么不能是/(\d{1,3}.){4}/这样,那是因为ip地址最后不能有小数点,否则12.231.23.200.将会匹配成功。

其实这个模式并不能完全正确地匹配ip地址,但主要传达的是对分组的理解。

例子三:

匹配年份19或20开头的年份。

var reg = /19|20\d{2}/;
var result = "1967".match(reg) //19

|表示或者的意思,表示匹配19或者20,后面再跟两个数字。但结果只匹配到了19。
这是因为|字符把左边的19看做一个整体,把右边的20\d{2}看做一个整体,所以左边匹配的不是19\d{2},而仅仅是19而已.

var reg = /(19|20)\d{2}/;
var result = "1967".match(reg) //1967

这样(19|20)的写法表示的是匹配这个分组中的两个选项之一。

19、回溯引用

回溯引用指的是在模式中后面引用前面的分组里的子表达式。

let reg = /([a,b])\1/g

在上面的模式中,\1就是一个引用,它引用的是谁呢?是前面的分组中的[a,b]这个子表达式。注意,只有用括号括起来的表达式才能被引用。
为什么叫引用呢?我们知道[a,b]匹配的是a或者b这个两个字母,[a,b]这个子表达式的匹配结果决定了\1将匹配的结果。
比方说,[a,b]这部分匹配到的是a,那么\1将匹配a,如果[a,b]这部分匹配到的是b,那么\1将匹配b。\1就如同一个变量,引用着被引用者的匹配结果。

let reg = /([a,b])\1/
var result = reg.test('aa') //true

[a,b]匹配到的是a,那么\1匹配到的也必须是a,结果返回true

let reg = /([a,b])\1/
var result = reg.test('ab') //false

[a,b]匹配到的是a,但是\1匹配到的却是b,结果返回false

let reg = /([a,b])([1,2])\1\2/g
let str = 'a1a1'
var result = reg.test(str) //true

引用可以有多个\1表示对第一个括号进行引用,\2表示对第二个括号进行引用,\3表示第三个,依次类推

例子:'<h1>abc<h1><h2>abc<h2><h3>abc<h3>'

现在的需求是,我们需要将字符串中的标题标签全都找出来。

let reg = /<h[1-6]>.*?<\/h[1-6]>/g
let str = '<h1>abc</h1><h2>abc</h2><h3>abc</h3>'
var result = str.match(reg) // ["<h1>abc</h1>", "<h2>abc</h2>", "<h3>abc</h3>"]

这样看似好像没有问题,但其实是有问题的。注意标签内需要把*元字符转换为懒惰型。

let reg = /<h[1-6]>.*?<\/h[1-6]>/g
let str = '<h1>abc</h1><h2>abc</h2><h5>abc</h6>'
var result = str.match(reg) // ["<h1>abc</h1>", "<h2>abc</h2>", "<h5>abc</h6>"]

可以看到<h5>abc</h6>这样的不合法标签也被匹配出来了。
这是因为当前面的<h[1-6]>匹配到的是h5的时候,后面的<h[1-6]>完全可以匹配h5之前的标签,因为我们把区间限定在了1-5之间
我们可以使用回溯引用,也就是当前面匹配的是h5的时候,后面匹配到的也必须是h5

let reg = /<h([1-6])>.*?<\/h\1>/g
let str = '<h1>abc</h1><h2>abc</h2><h5>abc</h6>'
var result = str.match(reg) // ["<h1>abc</h1>", "<h2>abc</h2>"]

可以看到,我们把前面的[1-6]放到了括号里,然后在结束标签中进行引用,解决了这一问题。

获取分组匹配的内容:

let reg = /([a,b])([1,2])/
let str = 'a1'
var result = reg.test(str)
console.log(RegExp.$1) //a
console.log(RegExp.$2) //1

$1表示第一个分组匹配到的内容
$2表示第二个分组匹配到的内容

例子:
把313-555-1234这样的电话号码格式转换为(313) 555-1234这的格式

/(\d{3})(-)(\d{3})(-)(\d{4})/.test('313-555-1234')
let newStr = `(${RegExp.$1}) ${RegExp.$3}-${RegExp.$5}`
console.log(newStr) //(313) 555-1234

20、分组的嵌套

/((逗|二|傻)比)\1/.test('逗比逗比') //true
/((逗|二|傻)比)\1/.test('二比二比') //true
/((逗|二|傻)比)\1/.test('傻比傻比') //true
/((逗|二|傻)比)\1/.test('傻比二比') //false 

/((逗|二|傻)比)\1/.test('傻比傻比') //true
console.log(RegExp.$2) //傻
console.log(RegExp.$1) //傻比

在上面的模式中,第二个分组(逗|二|傻)匹配逗,二,傻中的其中一个,
当匹配到傻的时候,与括号右边的"比"组成"傻比",而"傻比"就成了第一个分组的内容。
最后我们使用\1引用了第一个分组的匹配结果,所以"傻比傻比"与模式匹配,而"傻比二比"则不匹配。

21、?=向前查找与?!负向前查找

?=向前查找

let reg = /h(?=[1-6])/g;
let result = 'h1h2h3h4h5h6h7h8'.replace(reg, "H") 

console.log(result) //H1H2H3H4H5H6h7h8

?=元字符后面的内容表示满足的条件,这里为数字1-6,也就是当h后面跟着的是1-6的数字的时候,为满足条件匹配成功。
需要注意的是,与?=后面的内容相匹配的内容将不会在结果里返回。

let reg = /h(?=[1-6])/g;
let result = 'h1h2h3h4h5h6h7h8'.match(reg) 

console.log(result) //["h", "h", "h", "h", "h", "h"]

可以看到,数字部分不会被返回,这也是?=元字符与其他元字符不同的地方。

let reg = /h([1-6])/g;
let result = 'h1h2h3h4h5h6h7h8'.match(reg) 

console.log(result) //["h1", "h2", "h3", "h4", "h5", "h6"]

当去掉?=元字符的时候,数字部分被返回。

?!负向前查找

let reg = /h(?![1-6])/g;
let result = 'h1h2h3h4h5h6h7h8'.replace(reg, "H") 

console.log(result) //h1h2h3h4h5h6H7H8

这相当于一个取反的操作,可以看到,h后面的数字部分不是1-6的h都被替换掉了。
这意味着,?!元字符将在不满足?!后面的内容的时候为匹配成功。
返回的结果中依然不包括与?!后面内容相匹配的值。

22、\b与\B 边界限定符

1、
事实上,当\b匹配到字母数字下划线的时候,将返回false,其他如空格将返回true,表示一个单词到达了边界。

/a\b/.test('a1') //false
/a\b/.test('ab') //false
/a\b/.test('a_') //false
/a\b/.test('a ') //true
/a\b/.test('a#') //true

2、\B则与\b相反,当\B匹配到字母数字下划线的时候将返回true,其他的字符返回false,表示一个单词没有到达边界。

/a\B/.test('a1') //true
/a\B/.test('ab') //true
/a\B/.test('a_') //true
/a\B/.test('a ') //false
/a\B/.test('a#') //false

3、例子

var reg = /cat/g;
var str = 'mycat yourcat badcat cat';
var result = str.replace(reg,'dog') //mydog yourdog baddog dog

这里的需求是将字符串中cat换为dog,不包含mycat yourcat badcat这样的单词。但所有包含cat的词汇都被换成了dog。
这时候,可以使用单词边界。

var reg = /\bcat\b/g;
var str = 'mycat yourcat badcat cat';
var result = str.replace(reg,'dog') //mycat yourcat badcat dog

在这里,模式\bcat\b将匹配cat的左右两边都不是字母数字下划线的单词,
在被匹配的字符串中,只有最后一个cat的左右两边都没有字母数字或下划线,因此它是匹配的。

var reg = /\Bcat\B/g;
var str = 'mycat_ yourcat_ badcat_ cat';
var result = str.replace(reg,'dog') //mydog_ yourdog_ baddog_ cat

上面把模式中的\b换成了\B,结果取得了相反的结果。

23、exec方法

var reg = /a/;
var result = reg.exec("a")

console.log(result) //a

exec方法将返回匹配到的值,不匹配的时候返回null。

var reg = /a/g;
var result = reg.exec("aaaaa")

console.log(result) //a

需要注意的是,exec只返回第一次匹配到的值。

24、search方法,返回字符串的索引值。

var reg = /a/g;
var result = 'cba'.search(reg)

console.log(result) //2

25、replace方法,替换字符。

var reg = /a/;
var result = 'cba'.replace(reg,'A')

console.log(result) //cbA

replace方法接受两个参数,第一个是匹配的模式,或者是一个字符串,第二个参数的字符将对参数一中的字符进行替换。

26、split方法将根据给定的字符对字符串进行拆分,最后返回一个数组。

var reg = /-/;
var result = 'a-b-c-d'.split(reg)

console.log(result) //["a", "b", "c", "d"]

这里,根据字符"-",把字符串拆分成数组。

27、RegExp的静态属性

1、leftContext属性获取匹配的字符串的左边的内容

var reg = /B/;
'aaaaBxxxxx'.match(reg)
var result = RegExp.leftContext;

console.log(result) //'aaaa'

2、rightContext属性获取匹配的字符串的右边的内容

var reg = /B/;
'aaaaBxxxxx'.match(reg)
var result = RegExp.rightContext;

console.log(result) //'xxxxx'

3、lastMatch获取最后一次匹配到的内容

var reg = /g[1-6]d/g;
var str = 'g1dg2dg3d';
var result = str.match(reg)

console.log(RegExp.lastMatch) //g3d

4、lastParen获取最后一个分组的匹配内容

var reg = /(1)(2)(3)/;
var str = '123';
var result = str.match(reg)

console.log(RegExp.lastParen) //3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值