Javascript中的正则表达式总结与实践

2017-10-12  本文已影响0人  Katherine的小世界

正则表达式一直是我的弱项,基本都是避而远之的。这次还是咬咬牙关来看一下学习一下吧。连续看了两天,完全没有了解过正则的我,终于也有点小收获了。

当然,这些东西的学习,除了看<高级程序设计>,我还主要向这位大神学习了,要看更多的信息还是要学学他的。
https://juejin.im/post/5965943ff265da6c30653879
看完之后,我就在这里做总结了。

3a1479998e2fbad23c66caae2664d5a.png

一 先做一些实例吧。

1 将 '?a=4&b=99'转换成 {a:4,b:99}

a = '?w=3&f=5'
t = a.split(/=|\&|\?/)
t.shift()
k = {}
k[t[0]] = t[1]
k[t[2]]= t[3]
console.log(k)   // {w: "3", f: "5"}

2 dgfhfgh254bhku289fgdhdy675gfh,输出[254,289,675]

var t = 'dgfhfgh254bhku289fgdhdy675gfh'
var k = t.match(/[0-9]+/g)
console.log(k) //  ["254", "289", "675"]

3 var s1 = "get-element-by-id";转换成"getElementById"

var s1 = "get-element-by-id";  
s1.replace(/\-\w/g, function(x){return x.substr(1).toUpperCase()})  // "getElementById"

4 将 18888888转换为 "$18,888,888.00"

t = 18888888
t.toFixed(2).replace(/(?=(\d{3})+\b)/g,',').replace(/^/g, '$$')
"$18,888,888.00"

5 验证密码问题

6 括号的作用 以及match的输出以及匹配形式

teat = '2013-12-12'
reg = /(\d{4})-(\d{2})-(\d{2})/
teat.match(reg)
console.log(RegExp.$1)   //  2013
console.log(RegExp.$2)   // 12
console.log(RegExp.$3)   //  12

7 括号的作用,用来替换

teat = '2013-12-12'
reg = /(\d{4})-(\d{2})-(\d{2})/
console.log(teat.replace(reg, '$1/$2/$3'))
console.log(RegExp.$1)   //  2013
console.log(RegExp.$2)   // 12
console.log(RegExp.$3)   //  12

8 replace函数的作用,函数内的参数,这和括号属性是有关系的

var regex = /(\d{4})-(\d{2})-(\d{2})/; 
var string = "2017-06-12"; 
var result = string.replace(regex, function (match, year, month, day) {   
  return month + "/" + day + "/" + year;
 });
 console.log(result)

括号出现之后的反向引用,用\1,\2,\3去代表括号内的元素。

9 待解决的问题 为什么下面的输出会出现空格

var k = 'snnhuhdheheh'
console.log(k.split(/n/))
console.log(k.match(/n/))  \\ ["s", "", "huhdheheh"]

10 将字母的首字母变成大写

var test = 'you are my girl'
var reg = /\b\w{1}/g
test.replace(reg, function(match){
  return match.toUpperCase()
}) \\ "You Are My Girl"

11 驼峰化

var test = '-moz-tauia-www '
var reg = /\-.{1}/g
console.log(test.replace(reg, function(match){
return match.substr(1).toUpperCase()
}))  \\ MozTauiaWww 

反向引用的实际使用方法 匹配<title>sss</title>等双标签的语句。开闭标签要一样。

其中\1\2\3分别代表第几个引用分组。如果要使分组不会造成编码引用,需要设置成(?:)的格式

test1 = '<title>hudfuisyu</title>'
test2 = '<titl>hudfuisyu</title>'
test3 = '<p>hudfuisyu</p>'
reg = /\<([^>]+)\>.*\<\/\1\>/g
console.log(reg.test(test1))  \\ true
console.log(reg.test(test2))  \\ false
console.log(reg.test(test3))  \\ true

12 利用反向引用实现:正则去除字符串中出现的连续相同的字符

str = 'ABBBCCCDDDEEE'   // 匹配到的是出现连续相同的字符组,所以BBB,CCC,DDD都会被匹配到的,再依次替换就可以了
reg = /(.)\1{1,}/g
str.replace(reg, '$1')
"ABCDE"

13 关于位置的匹配 (?=p)和 (?!p)

(?=p)表示的是后面有出现p的位置,当然,在正则匹配中,表示匹配到的字符串后面需要有p
(?!p) 表示的是后面不能出现p的位置。
而且位置匹配不会匹配到字符串中,只是一个位置的标志匹配而已,这一点在替换的时候很重要

举个例子,我想要实现的是,查找字符串,只要出现有两个以上的换行符就匹配结束。而且以@ 为开头。

regex: /^@\s([\s\S]*?)(?=\n{2,})/gm    // 这里我使用的是(?=\n{2,})这样只要匹配到有两个以上的n的位置。
当然第一个括号内的?也很重要,是惰性匹配。以防后面也有出现两个\n以上的会继续往后面匹配。
然后我的目的是匹配之后我要做替换,但是我不希望出现的换行符被我替换掉,所以我要用这个位置属性。

// 其实对这个位置属性的理解,就是,如果单独使用他,那么就是直接匹配到了某个位置,这个位置就是字符与字符之间的空隙
//  如果和其他的字符结合,那就是结合之后在满足要求的位置处停止。
// 如果单独使用,就是匹配到那个满足的位置那里。

二 常用方法的总结与实践

string的方法

1 search(验证)

接受一个参数,正则表达式或者RegExp对象。(字符串会转换成正则),返回字符串中第一个匹配项的索引。
如果没有索引值,就返回-1。始终是从头开始向后查找的。

注意问题:字符串会转换成正则,所以需要输入的是正则表达式

var string = "2017.06.27"; 
console.log( string.search(".") ); // => 0 ,因为‘.‘会被转换成/./就是任意字符。
//需要修改成下列形式之一 
console.log( string.search(/\./) ); // => 4

2 replace(替换)

接受两个参数,第一个是正则对象或者字符串(不会被转成正则表达式)。第二个参数可以是字符串或者函数,如果是字符,还可以使用特殊的字符序列。$&,匹配整个模式的字符串。$n,匹配第n个捕获组的字符串。

当存在+的时候,对于括号内的匹配,匹配的是最后一项。

var test = 'eeek'
var reg = /(\w{1})+/
test.replace(reg, '$1++')  //"k++"

匹配的是最后一个分组的了。如果想要把每一个分组都列出来,想必是要加多个括号来了。
replace的一些参数属性

image.png

精彩组合!!!:replace 结合 正则表达式()的分组,实现分组替换。

var reg = /(\d{4})-(\d{2})-(\d{2})/
var test = '2019-12-12'
test.replace(reg, '$2/$3/$1')  // 12/12/2019 // 其中,每一个匹配的模块要用()括起来,分别对应$1,$2,$3。如果没有用括号括起来,就不会有这些值啦。
var reg = /(\d{4})-(\d{2})-(\d{2})/
var test = '2019-12-12'
test.replace(reg, function(match, w,r,e) {
return e + '/' + r + '/' + w
}) // 12/12/2019,其中,match 是匹配的整体字符串,w,r,e分别是子匹配模块。
var regex = /(\d{4})-(\d{2})-(\d{2})/; 
var string = "2017-06-12";
var result = string.replace(regex, function () {
  return RegExp.$2 + "/" + RegExp.$3 + "/" + RegExp.$1; 
}); 
 console.log(result);  // 12/06/2017

3 match(匹配)

接受一个参数,正则表达式或者RegExp对象。
返回视情况而定。(字符串会改成正则)返回:一个由匹配结果组成的数组。有g,则返回所有匹配结果。// ["2019-12-12"]
无g,返回的数组第一个元素是匹配的字符串,剩下的是圆括号分组的子表达式。a[n]存放的是$n的内容。 //["2019-12-12", "2019", "12", "12", index: 0, input: "2019-12-12"]

- 1 提取,通过match的匹配特点,结合()分组匹配,获取子匹配模块。
var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/; 
var string = "2017-06-26"; 
console.log( string.match(regex) );
 // =>["2017-06-26", "2017", "06", "26", index: 0, input: "2017-06-26"]

2 全局匹配和非全局匹配的输出结果区别

!!!match 在非全局匹配的情况,输出匹配项以及子匹配模块还有index和input。

match在全局匹配的情况,则只返回匹配的子字符串。不会返回匹配字符串下的子模块。

var string = "2017.06.27";
var regex1 = /\b(\d+)\b/; 
var regex2 = /\b(\d+)\b/g; 
console.log( string.match(regex1) ); // => ["2017", "2017", index: 0, input: "2017.06.27"],
console.log( string.match(regex2) );  // => ["2017", "06", "27"]


var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/; 
var regex1 = /^(\d{4})\D(\d{2})\D(\d{2})$/g;
var string = "2017-06-26"; 
console.log( string.match(regex) ); //  ["2017-06-26", "2017", "06", "26", index: 0, input: "2017-06-26"]
console.log( string.match(regex1) ); //  ["2017-06-26"]

4 split(切分)

接受一个参数,该参数可以分割成多个字符串,参数可以是一个RegExp对象也可以是字符串(字符串不会被看作是正则表达式。)可以有两个参数,第二个参数是返回的数组的长度。

// 拆分 2017/06/26 2017.06.26 2017-06-26
var test = '2017/06/26'
var test2 = '2017.06.26'
var test3 = '2017-06-26'
var reg = /[\.\/-]/g
console.log(test.split(reg)) // [2017,06,26]

正则的一些方法

1 test()

接受一个字符串参数。在模式与该参数匹配的情况下则返回true。否则返回false。

常用语if语句判断中,用于检测某一些信息格式是否正确,只需要部分匹配即可一返回true。如果需要整体去匹配,则需要考虑^$来限定匹配的开始和结束。

2 exec()

接受一个参数,要匹配的字符串。返回一个包含匹配信息的数组,包含Input和index两个额外属性。第一个项是与整个模式匹配的字符串,其他项是与模式中的捕获组(也就是括号内的)匹配的字符串。
有g。每次返回的都只是第一个匹配项,除非再接下来进行操作一次,才会在原来的基础上继续进行匹配。
无g。每次返回的是第一次匹配项的信息(包含整个匹配的字符串以及字符串内部相应的多个捕获组以及index和input)

!其实,exec()和字符串的match()是很相似的。
但是match在全局匹配下却不能给太多完整的信息。
1 match()在全局匹配的时候,输出的是匹配的项(不包含捕获组)
2 而exec()在全局捕获的时候,输出的是匹配的项以及相应的捕获组,index,input

感觉,exec()输出的信息会更多,不过它有一个缺点,就是即使是全局匹配,每次也只是输出第一次匹配的项目信息,要再次输出就得再执行一次exec().所以exec()经常会与循环结合使用


var test = 'yousiusdh123huus211wwww'
var reg = /\d{3}(\w{3})/g
var k = reg.exec(test)
console.log(k)
var t = reg.exec(test)
console.log(t)
// ["123huu", "huu", index: 9, input: "yousiusdh123huus211wwww"]
//["211www", "www", index: 16, input: "yousiusdh123huus211wwww"]
var test = 'yousiusdh123huus211wwww'
var reg = /\d{3}(\w{3})/g
var k = reg.exec(test)  // 输出第一次匹配项以及捕获组匹配,index,input
var l = test.match(reg) // 输出的是所有的匹配项(不包含捕获组)
console.log(k)  // ["123huu", "huu", index: 9, input: "yousiusdh123huus211wwww"]
console.log(l) // ["123huu", "211www"]
var test = 'yousiusdh123huus211wwww'
var reg = /\d{3}(\w{3})/
var k = reg.exec(test)   // ["123huu", "huu", index: 9, input: "yousiusdh123huus211wwww"]
var l = test.match(reg) //  ["123huu", "huu", index: 9, input: "yousiusdh123huus211wwww"]

3 正则实例的lastIndex属性

当使用exec和test方法的时候,正则实例的lastIndex都会跟着改变。如果包含有g,则每次执行完之后都会发生改变,如果不含g,则每次都是从0开始的。

var test = 'abcabababa'
var test2 = 'abc'
var test3 = 'abcab'
var test4 = 'abdsksj'
var reg = /ab/g
console.log(reg.test(test2), reg.lastIndex) // true 2
console.log(reg.test(test3), reg.lastIndex) //  true 5
console.log(reg.test(test), reg.lastIndex) //   true 7
console.log(reg.test(test4), reg.lastIndex)  //  false 0

二 当然,match在非全局匹配模式下,输出的信息就和exec()的一样了。几乎功能和exec()

四 常见的元字符

( { [ \ ^ $| ) ? * + . }]

五 正则表达式中

字面量形式与构造函数实例的区别

字面量模式

var pattern = /[bc]at/g

构造函数形式,j接受的是匹配的字符串模式,另一个是可选的标志字符串

var pattern2 = new RegExp('[bc]at', g)

2 区别:使用正则表达式字面量始终会共享同一个RegExp实例,而使用构造函数创建的每一个RegExp都是一个新实例。

注意:首先要知道, 当使用g模式进行test()检测的时候,每多执行一次test(),如果是同一个正则表达式,就会再次从上次检测到的位置开始继续检测,而不是从index=0从头检测。
所以,通过下面的例子可以发现,第一个for循环,执行第一次的时候是输出true,之后就输出false,因为之后再次执行的就接着上次执行到的位置继续执行,因为正则表达式字面量始终共享同一个RegExp实例
而第二个例子,则每次都输出true,因为每次都是重新从index= 0 的位置开始检测

var re = null
             i;
for (i =0; i < 10; i++) {
  re = /cat/g
  re.test('catshishsus')
}
for (i=0;i<10;i++) {
  re = new RegExp('cat', 'g')
  re.test('catcskjlsl')
}

五 RegExp构造函数的一些属性

var test = 'yousiusdh123rhuus211wwww'
var reg = /\d{3}(\w{3})/
 test.match(reg)
console.log(RegExp.$1) //  rhu
image.png

参考链接:
http://imweb.io/topic/56e804ef1a5f05dc50643106
https://juejin.im/post/5965943ff265da6c30653879

上一篇下一篇

猜你喜欢

热点阅读