javaScript之正则常用方法

1,476 阅读7分钟

正则,RegExp,javaScript内置对象。正则表达式(regular expression)是一种表达文本模式(即字符串结构)的方法,有点像字符串的模板,常常用来按照“给定模式”匹配文本。通俗的讲就是,定义一个规则,检测某个字符串是否符合该规则。今天给大家分享正则的一些使用技巧和方法,元字符的认识,什么是贪婪模式,什么是懒惰模式,创建正则字面量和实例创建的区别,下面是目录列表:

  • 【1】创建正则
  • 【2】正则方法test和exec
  • 【3】正则属性lastIndex,source
  • 【4】修饰符
  • 【5】字面量字符和元字符
  • 【6】量词符
  • 【7】贪婪模式和懒惰模式
  • 【8】搭配字符串方法replace,macth,search,split

创建正则

正则的创建跟其他内置对象一样,有两种创建方式,字面量方式和实例创建方式两种: `

var str = '2018study'
var reg = /\d/g;     //字面量方式
var rex = new RegExp('\\d', 'g');    // 实例创建方式

`正则的两种创建方式,它们之间是有区别的,通过上面的代码,我们其实可以看到第一个区别,在我们字面量方式当中使用的'\d',在实例创建的方式里变成了'\\d',这是因为,在我们字面量的创建方式里,//里面包括的所有内容都是元字符,而反斜杠\在元字符里是有它的特殊含义的,它的含义就是转义,通俗的解释就是转变原来的意思;而实例创建的方式里,它的正则规则是定义在参数一,而参数一是可以使用字符串的形式定义规则的,所以需要转义一下,以便符合我们的需求,当然在构造函数里也可以使用直接量的形式,那样写就不需要转义了new RegExp(/d+/g)。这个区别也许不是那么明显,我们在看下面的例子:

`

var type = 'javascript'
var str = '2018study'+type;
var reg = /\d+study+"+type+"/g;     //字面量方式
console.log(reg.test(str);   // 输出 false

var rex = new RegExp("\\d+study"+type, 'g');    // 实例创建方式
console.log(rex.test(str));   // 输出 true

`上面的例子,我们是给需要验证的字符串添加了一个变量,也就是说,我们需要验证的字符串对象不是一个固定的,而是一个可变的,在这样的情况下,字面量创建方式是不能满足我们的需求的,而在我们的实例创建,正是因为我们的参数一本身是个字符串,所以我们可以进行变量的拼接。

正则方法test和exec 实例方法test,用来验证是否符合正则规则,返回个布尔值true或者false,实例方法exec,用来捕获符合正则规则的字符,并以数组的形式返回出来。下面请看例子: `

var tel = /^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$/
var str1 = '13358897665', str2 = '14479798800'
console.log(tel.test(str1));    // 输出 true
console.log(tel.test(str2));    //输出 false

var num = /\d+/g;
var str = '2018study';
console.log(num.exec(str))  // 输出["2018", index: 0, input: "2018study"]

`上面的例子,test是展示了一个对手机号码的一个验证,exec是对数字的一个捕获。

正则属性lastIndex,source

正则的属性,相信不少人对它们比较陌生,因为正则的属性在实际开发工作当中使用的频率比起上面的两个方法是比较少,下面我们看这两个的用法lastIndex,source: `

var str = 'Studying in 2018 and working in 2019';
var num = /\d+/g;
console.log(num.lastIndex)  //输出 0
console.log(num.exec(str))  // ["2018", index: 12, input: "Studying in 2018 and working in 2019"]
		
console.log(num.lastIndex)  //输出 16
console.log(num.exec(str))  // ["2019", index: 32, input: "Studying in 2018 and working in 2019"]
		
console.log(num.lastIndex)  //输出 36
console.log(num.exec(str))  // 输出null

` 上面的输出可以看出,只要字符串的可匹配内容没有匹配完,是可以重复使用exec进行捕获,而lastIndex就是记录了上一次匹配结束的位置,下面我们用个循环来实现重复捕获:

`

var str = 'Studying in 2018 and working in 2019';
var num = /\d+/g;
arr = []
while(num.lastIndex < str.length) {
	var numArr = num.exec(str);
		arr.push(numArr[0])
	}
console.log(arr)    // ['2018', '2019']

`我们在来看source用法:

`

var type = 'javascript'
var str = '2018study'+type;

var rex = new RegExp("\\d+study"+type, 'g');    // 实例创建方式
console.log(rex.source);   // 输出 \d+studyjavascript

`通过这个例子,我们可以看到source是用来获取我们这个正则表达式的,在处理传递了变量的正则,用此属性去获取,还是非常靠谱的。

修饰符

RegExp.prototype.ignoreCase:返回一个布尔值,表示是否设置了i修饰符,i修饰符忽略大小写;RegExp.prototype.global:返回一个布尔值,表示是否设置了g修饰符,g修饰符全局匹配;RegExp.prototype.multiline:返回一个布尔值,表示是否设置了m修饰符,m修饰符多行匹配;在字面量创建的正则,只需要把修饰符的字母,紧跟在表达式的后面就好了,而构建函数创建的正则,则可以使用第二个参数传递,下面看代码演示: `

var str = 'Studying in 2018 and working in 2019';
var regNum = /\d+/g;   // 使用修饰符g
regNum.global; // 输出true;
var numArr = str.match(regNum); // 输出: ['2018', '2019']	
 
var regNum1 = /\d+/;   // 未使用修饰符g
regNum1.global; // 输出 false;
var numArr1 = str.match(regNum1);// 输出: ['2018']	
 
var str2 = 'Hello 1234 word 5678 09';
var rexA = /[a-z]+/gi   //使用修饰符i
rexA.ignoreCase;    // 输出 true
str2.match(rexA)    // 输出 ['Hello', 'word']

var rexB = /[a-z]+/g    //未使用修饰符i
rexB.ignoreCase;    // 输出 false
str2.match(rexB)    // 输出 ['ello', 'word']

`在上面的例子中,展示了修饰符g和i的用法,m修饰符呢,留给js学习的同学自行测试一下,顺便在说一下,es6的规范出来后,又新增了两个修饰符u和y,u修饰符,含义为“Unicode 模式”,用来正确处理大于\uFFFF的 Unicode 字符。也就是说,会正确处理四个字节的 UTF-16 编码; y修饰符的作用与g修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始,不同之处在于,g修饰符只要剩余位置中存在匹配就可,而y修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。这两个修饰符本章节也不在演示,有兴趣的同学可以去阮一峰老师的ES6入门查看。

字面量字符和元字符

大部分字符在正则表达式中,就是字面的含义,比如/a/匹配a,/b/匹配b。如果在正则表达式之中,某个字符只表示它字面的含义(就像前面的a和b),那么它们就叫做“字面量字符”(literal characters)。除了字面量字符以外,还有一部分字符有特殊含义,不代表字面的意思。它们叫做“元字符”(metacharacters)。 `

var s1 = 'abc';
var re = /abc/;   // 这个正则里的匹配规则就是字面量字符

var s2 = '123';
var rx = /\d/; 这个正则里的匹配规则就是元字符

`下面介绍部分元字符:

  • . 点子符,匹配单个字符,除了换行和行结束符;
  • ^ 位置元字符,表示字符串的开始位置;
  • $ 位置元字符,表示字符串的结束位置;
  • | 选择元字符,表示或者的意思;
  • \d匹配数字;
  • \D匹配除了除了数字以外的字符;
  • \w匹配单词字符;
  • \W匹配非单词的字符;
  • \n匹配换行符;
  • \r匹配回车符;
  • [] 限制范围范围符;例如:/[abc]/,只可以匹配到'abc';
  • [^]中括号里使用^称谓排除符,意思是除了中括号里的字符,其他全匹配,例如:/[^abc]/,可以匹配到'j','s',匹配不到'a','b','c'。
  • ()小括号为分组符,所谓分组符,就是在大的正则规则里分成一个小正则。

量词符 量词符,通俗的理解就是匹配数量的意思,匹配一个还是两个或者多个。在我们之前的例子中也有使用,就是+号,+表示匹配至少一个,或者多个,看示例: `

var num = '123456789'
var re = /\d/;   // 不使用量词符
num.match(re); //输出 ['1']

var rg = /\d+/
num.match(rg); //输出 ['123456789']

`上面的例子就体现量词符的含义,数量。下面介绍部分量词符:

  • + 匹配至少一个或者多个的字符;
  • * 匹配0个或者多个字符;
  • ? 匹配0个或者1个字符,?是个特殊的量词符,它具有多种含义,下面单独看例子;
  • {n} 匹配n次的字符,/a{2}/ 不匹配 "candy," 中的 "a",但是匹配 "caandy," 中的两个 "a";
  • {n,}n是一个正整数。前面的模式 n 连续出现至少 n 次时匹配。 例如,/a{2,}/ 不匹配 "candy" 中的 "a",但是匹配 "caandy" 和 "caaaaaaandy." 中所有的 "a"。
  • {n,m} n 和 m 为正整数。前面的模式 n 连续出现至少 n 次,至多 m 次时匹配。

`

// ?量词符 示例
var re = /a?/
var str = 'abc', str1 = 'cbd'; 
re.test(str); // true   
re.test(str1); // true

var str2 = 'aaabc'
var re = /a+?/; /合量词符+号后面使用,*号后面使用,exec捕获就只会返回有一个空字符的数组
re.exec(str2); // ['a']

var sfz = '456077198808064610'; //
var rez = /^(\d{6})(\d{8})(\d{2})(\d)(\d)$/;    //未配合冒号
rez.exec(sfz)   // ["456077198808064610", "456077", "19880806", "46", "1", "0", index: 0, input: "456077198808064610"]

var reg = /^(\d{6})(\d{8})(?:\d{2})(\d)(\d)$/;  // 配合:冒号使用,只匹配,不返回
rez.exec(sfz)   // ["456077198808064610", "456077", "19880806", "1", "0", index: 0, input: "456077198808064610"]

`这里考虑篇幅的问题,所以并没有展示完全,这里的示例主要是说明元字符?它具备多种含义在使用的过程中请一定注意它表达的含义,这里分享一个链接,各位同学如要了解,可以去正则元字符查看。

贪婪模式和懒惰模式

在正则的概念里,有贪婪模式和懒惰模式,贪婪模式和懒惰模式的概念并不难理解,在我们上面的例子里其实早就展示过,只是没有提出来而已,下面我们看例子说明: `

var str2 = 'aaaaaaaabcdefgaaa'
var re = /a/; 
re.exec(str2); // ['a'],这里之所以只捕获到一个a,就是因为这个正则是个懒惰模式,明明那么多个a,它就是不多匹配,能少匹配就少匹配,

var re = /a+/
re.exec(str2); // ['aaaaaaaa'],这里正则是贪婪模式,在第一次的匹配当中,只要是连接在一起的a,它都会匹配下来,不管你多少个a,当然这个正则也可以说它是又懒又贪的,懒是因为后面还有3个a,但是它就没有匹配,是因为没有给它加修饰符g。

`

搭配字符串方法replace,macth,search,split

  • match():返回一个数组,成员是所有匹配的子字符串。
  • search():按照给定的正则表达式进行搜索,返回一个整数,表示匹配开始的位置。
  • replace():按照给定的正则表达式进行替换,返回替换后的字符串。
  • split():按照给定规则进行字符串分割,返回一个数组,包含分割后的各个成员。

下面看各个的示例展示: `

var str = '2018结束了,2019开始了,2020年也不远了';
var reg = /\d+/g;

str.match(reg)  // 输出['2018', '2019', '2020'];

str.replace(reg,'****') // 输出 '****结束了,****开始了,****年也不远了'

var rex = /开始/g;
str.search(rex);    //输出 12,所在字符串的索引位置

var re = /,/g;
str.split(re)   // 输出:["2018结束了", "2019开始了", "2020年也不远了"]

`

结语

正则对象,自己本身的方法并不多,但是正则在对字符串的操作处理上面,确是一大顶级利器。而正则真正复杂的地方,是对元字符的理解和认识,只要对元字符有正确的认识和理解,就可以定义出自己需要的正则规则来,今天分享就到这,觉得还行的朋友帮点个赞,以示鼓励,谢谢。