JS之正则表达式

  正则表达式(英文:regular expression),是一种符合某种语法规则的文本。同时可以理解为使用单个字符串来描述,匹配一系列的符合某种语法规则的字符串。许多语言都有着符合自己语法规范的正则表达式,如java,python,php,js。虽然这些正则不是完全一样,但也是大同小异。今天我想重点说的是JS中的正则表达式。

 

  正则表达式的功能十分强大,能够熟练掌握它能够为平时的学习和工作带来不少的便利。虽然正则理解入门不是很难,但是真正地去掌握它并且熟练地运用起来却不是一件容易的事情。

 

  学习正则有一个很好的在线的网站 https://regexper.com/  。它可以帮助你更好的理解正则表达式中的一些关系。

 

正则表达式基础语法内容

1.1正则表达式的构造

  在js中,正则表达式有两种构造方式。一种是常用的字面量表示法,即将正则字符串写在/(regexp)/

  例如要匹配一个数字

var reg=/\d/;

  还有一种是构造函数的方法,即new RegExp()。该方法有接收两个参数,第一个参数是正则字符串,第二个是匹配的模式(下文会讲)。但是第一个参数比较特殊,在转义字符时同时要转义转义字符,即若是用这种方法匹配一个数字,

var reg=new RegExp('\\d','g');

1.2正则表达式的匹配模式

  常见匹配模式有三种,即全局匹配g,不区分大小写i,多行搜索匹配m。

'abcd'.replace(/[a-z]/,'1')  //'1dcd'  只匹配一次

'abcd'.replace(/[a-z]/g,'1') //'1111'  都可以被匹配

'ABcd'.replace(/[a-z]/,'1')  // 'AB1d' 

'ABcd'.replace(/[a-z]/gi,'1') //'1111'

'a
b
c'.replace(/^[a-z]/,'1') 
//'1
b
c'
//换行符隔开
'a
b
c'.replace(/^[a-z]/m,'1') 
//'1
1
1'

 

2.正则表达式语法

2.1元字符

  正则表达式由两种基本字符类型组成:①.原义文本字符,就是字符本身代表的意思。如 a 匹配 a ,1匹配1     ②.元字符,即正则中有特殊含义的非字母字符 如  *  +  ?  $  ^ . |  \ ()  {}  []

  元字符构成了许多有意义的特殊字符,例如 \t 水平制表符  \v垂直制表符  \n换行符  \r回车符  \0空字符  \f换页符  

2.2字符类

  一般情况下正则中一个字符匹配字符串中的一个字符,但是可以用元字符[]来构建一个符合某种特性的类,即符合这种特性的字符都可以被匹配。如[a,b,c]匹配a或b或c

'abcd'.replace(/[abc]/g,'d')   //'dddd'   即abc都可以被匹配

2.2.1字符类取反

  使用元字符^可以创建反向类,即不属于某种类的内容 如[^abc]匹配不是abc的字符

'abcde'.replace(/[^abc]/g,'x')  //'abcxx'  即把不是abc的字符替换为x

2.2.2范围类

  可以在[]中用-来连接两个字符表示范围  如[a-z]相当于[abcd.....xyz],[0-9]相当于[0123456789],这样带来了许多便利。

  在范围类的内部可以连写。如[a-zA-Z]匹配所有大小写字母。如果要匹配-则要在之后加上-,在两个字符之间的-表示范围。

'1970-01-01'.replace(/[0-9]/g,'a')  //'aaaa-aa-aa' 

'1970-01-01'.replace(/[0-9-]/g,'a')   //'aaaaaaaaaa'

2.2.3预定义类

  ①.可以匹配常见的字符类.

  例如  .匹配除了回车符和换行符(\r\n)之外的所有字符 ;\d([0-9])匹配数字字符,\D([^0-9])匹配非数字字符;\s([\t\n\x0B\f\r])匹配空白符,\S([^\t\n\x0B\f\r])匹配非空白符;\w([a-zA-Z_0-9])匹配单词字符,\W([^a-zA-Z_0-9])匹配非单词字符.

  ②.边界匹配字符.如^  表示以xxx开头(这里要注意区分开反向类,它在[]外,在[]内部表示取反)  $表示以xxx结尾  \b表示单词边界  \B表示非单词边界。

2.3量词

  量词表示可以匹配任意数量的字符串.如?表示匹配0次或1次,+表示匹配1次或多次,*表示匹配0次或多次 ,{n}表示匹配n次,{n,m}表示匹配n次到m次,{n,}表示匹配至少n次

'abcd'.replace(/[a-z]?/,'x')  //'xbcd'

'abcd'.replace(/[a-z]+/,'x') //'x'

'abcd'.replace(/[a-z]*/,'x')  //'x'

'abcd'.replace(/[a-z]{2,3}/,'x') // 'xd'

以上都是在贪婪模式下匹配返回的字符串,这是正则默认的匹配模式,下文会详细说明

2.4贪婪模式与非贪婪模式.

  贪婪模式是正则表示式默认的匹配模式,即尽可能多的匹配字符。非贪婪模式则相反,尽可能少的匹配,一旦匹配成功则不再尝试。

  贪婪模式如下

'12345678'.replace(/\d{3,6}/g,'0')  //'078'

  非贪婪模式,只需在量词后加上?就可以了。

'12345678'.replace(/\d{3,6}?/g,'0')  //'0078'

2.5分组

  ①分组表示可以将不同的正则分为一组去匹配字符串。用()括起来的部分表示一个分组。如([a-z]\d)表示一个小写字母与一个数字为一组

'a1b2c3d4'.replace(/([a-z]\d){3}/g,'x') //'xd4'

  ②或,用 | 表示。例如

'cathatbat'.replace(/[c|h|b]at/g,'x') // 'xxx'

  ③反向引用,在正则中很重要的一个方法.$1,$2,$3...$n表示的是分组内的内容,分组上文讲过用()括起来的是一个分组,用$捕获分组内的内容,也叫捕获组。

  如要将1970-01-01替换成01/01/1970

'1970-01-01'.replace(/(\d{4})-(\d{2})-(\d{2})/g,'$2/$3/$1')

// 01/01/1970

  ④忽略分组,若不希望捕获某些分组,只需要在分组内加上?: 就可以了

 2.6前瞻后顾

  前瞻就是正则表达式匹配到规则时,向前检查是否符合断言,后顾方向相反。JS中不支持后顾。

  正向前瞻 exp(?=assert)

 

'a2*3'.replace(/\w(?=\d)/g,'x')  //'x2*3'

 

   负向前瞻 exp(?!assert)

 

'a2*3'.replace(/\w(?!\d)/g,'x')  //  'ax*3'

 

3.RegExp对象

3.1.RegExp对象属性

global:是否全文搜索,默认为false,只读

ingore case:是否大小写敏感,默认为false,只读

multiline:是否多行搜索,默认为false,只读

lastIndex:当前表达式匹配内容的最后一个字符的下一个字符的位置,只在全局匹配中有作用

source:正则表达式的文本字符串

3.2.RegExp对象的相关方法

①.RegExp.prototype.test(str)

用于测试字符串参数中是否存在匹配正则表达式模式的字符串,存在返回true,不存在返回false

这里要注意一个问题,就是关于lastIndex指向问题

var reg=/\w/g ;

reg.test('ab') //第一次  返回true 没问题

reg.test('ab') //第二次  返回true  没问题

reg.test('ab') //第三次  返回false  有问题

reg.test('ab') //第四次 返回true
while(reg.test('ab')){ console.log(reg.lastIndex); } // 1 2

正则表达式对象每次匹配都作用在正则表示式本身,每次匹配成功都会去根据lastIndex去寻找下一个字符是否匹配,若没有则lastIndex会被重置成0。

 

②.RegExp.prototype.exec(str)

使用正则表达式对字符串执行搜索,并将更新全局RegExp对象的属性以反映匹配结果。如果没有匹配的文本返回null,否则返回一个结果数组。

该结果数组中有两个特别的对象属性:

index:声明匹配文本的第一个字符的位置,

input:存放匹配的字符串

第一个元素是与正则表达式想匹配的文本

第二个元素是与RegExp对象的第一个子表达式想匹配的文本

第三个是与RegExp对象的第二个子表达式匹配的文本,以此类推

var reg1=/\d(\w)\d/;
var reg2=/\d(\w)\d/g;
var str='1a2b3c4d5e';

reg1.exec(str)
 //["1a2", "a", index: 0, input:"1a2b3c4d5e"]


reg2.exec(str)
//["1a2", "a", index: 0, input: "1a2b3c4d5e"]

4.字符串对象与正则相关的方法

①String.prototype.search(reg)

用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串

返回第一个匹配结果的index,若查找不到则返回-1,

不执行全局匹配,忽略g标志。

'a1b2c3d1'.search(/1/) //1

'a1b2c3d1'.search(/1/g)  //1  忽略g标志

②String.prototype.match(reg)

用于检索字符串,以找到一个或多个与regexp匹配的文本,是否具有g标志对结果影响很大

非全局调用

只执行一次匹配,没有找到匹配文本则返回null,否则返回一个数组,其中存放了与它找到匹配文本相关的信息。

该结果数组中有两个特别的对象属性:

index:声明匹配文本的第一个字符的位置,

input:存放匹配的字符串

第一个元素是与正则表达式想匹配的文本

第二个元素是与RegExp对象的第一个子表达式想匹配的文本

第三个是与RegExp对象的第二个子表达式匹配的文本,以此类推

这与RegExp对象的exec方法很类似,只是字符串与正则表达式的位子互换了。

全局调用

执行全局搜索,找到字符串中的所有匹配子字符串,没有找到返回null,否则返回一个数组,其中存放了与它找到匹配文本的相关信息。

该结果数组中有两个特别的对象属性:

index:声明匹配文本的第一个字符的位置,

input:存放匹配的字符串

数组中的元素存放的是字符串中所有的匹配到的子字符串

③String.prototype.split(reg)

split方法是我们熟悉的方法,我们经常用split将一个字符串分割成一个数组,同样的这个分割符可以是一个正则表达式.

'a1b2c3d'.split(/\d/g)  //["a", "b", "c", "d"]

④.String.prototype.replace()

这个方法是特别重要也相对较复杂的方法,功能特别强大的一个方法。

它有两个参数,第一个参数是需要被替换的字符串,第二个参数是用来替换的字符串。

它有三种使用方法

String.prototype.replace(str,newStr),

String.prototype.replace(reg,newStr),

String.prototype.replace(reg,function)

重点就在于String.prototype.replace(reg,function)

function的返回值是替换结果.这个function在每次匹配替换的时候被调用,有四个参数

1.匹配的字符串

2.正则表达式分组内容,没有分组则没有该参数

3.匹配项在字符串中的index

4.原字符串

//没有分组的情况
'a1b2c3d4'.replace(/\d/g,function(match,index,origin){ return parseInt(match)+1; }) //"a2b3c4d5"
//有分组的情况
'a1b2c3d4'.replace(/(\d)(\w)(\d)/g,function(match,group1,group2,group3,index,origin){ return group1+group3; }) //"a12c34"

以上就是正则表达式的大部分内容。正则表达式功能很强大,能熟练应用会给我们带来很多便利。

posted @ 2017-09-03 11:32  Eric1997  阅读(267)  评论(0编辑  收藏  举报