javascript教程_JavaScript 正则表达式 极简教程

dd86225f953de538fd0bfcd4395dde4f.png

0.前言

关于js的正则,它非常有用,掌握好正则,将会对代码逻辑的实现和业务的稳定性有很大帮助。但是正则表达式方法众多,规则难记。在此,我分享一下我的学习和记忆方法:首先理解正则表达式的创建以及参数的含义。其次弄明白和正则相关方法的分类(正则对象方法(RegExp.prototype)和字符串方法(string.prototype))和用法。然后要知道正则的一些默认行为,比如正则默认是贪婪匹配。最后要搞懂匹配规则,这些规则也要分组来记忆,比如元字符、转义符、预定义模式等。

1.概述

正则表达式(regular expression)用来按照“给定模式”匹配文本。常用来匹配Email地址等文本匹配。

创建正则表达式有两种方式:

var regex = /xyz/i;
var regex = new RegExp('xyz',i);

上面两种写法是等价的,都新建了一个正则表达式对象。推荐使用前者,因为前者的效率较高、便利且直观。


2.实例属性

  • RegExp.prototype.ignoreCase:返回一个布尔值,表示是否设置了i修饰符。
  • RegExp.prototype.global:返回一个布尔值,表示是否设置了g修饰符。
  • RegExp.prototype.multiline:返回一个布尔值,表示是否设置了m修饰符
  • RegExp.prototype.lastIndex:返回一个数值,表示下一次开始搜索的位置。该属性可读写,但是只在进行连续搜索时有意义。
  • RegExp.prototype.source:返回正则表达式的字符串形式(不包括反斜杠),该属性只读。

3.实例方法

3.1 RegExp.prototype.test()

返回一个布尔值,表示当前模式是否能匹配参数字符串。

如果正则表达式带有g修饰符,则每一次test方法都从上一次结束的位置开始向后匹配。

var r = /x/g;
var s = '_x_x';

r.lastIndex // 0
r.test(s) // true

r.lastIndex // 2
r.test(s) // true

r.lastIndex // 4
r.test(s) // false

带有g修饰符时,可以通过正则对象的lastIndex属性指定开始搜索的位置

var r = /x/g;
var s = '_x_x';

r.lastIndex = 4;
r.test(s) // false

3.2 RegExp.prototype.exec()

返回匹配结果。如果发现匹配,就返回一个数组,成员是匹配成功的子字符串,否则返回null

var s = '_x_x';
var r1 = /x/;
var r2 = /y/;

r1.exec(s) // ["x"]
r2.exec(s) // null

如果正则表示式包含圆括号(即含有“组匹配”),则返回的数组会包括多个成员。第一个成员是整个匹配成功的结果,后面的成员就是圆括号对应的匹配成功的组。也就是说,第二个成员对应第一个括号,第三个成员对应第二个括号,以此类推。

var s = '_x_x';
var r = /_(x)/;

r.exec(s) // ["_x", "x"]

如果正则表达式加上g修饰符,则可以使用多次exec方法,下一次搜索的位置从上一次匹配成功结束的位置开始。

var reg = /a/g;
var str = 'abc_abc_abc'

while(true) {
  var match = reg.exec(str);
  if (!match) break;
  console.log('#' + match.index + ':' + match[0]);
}

4. 字符串的实例方法

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

4.1 String.prototype.match()

对字符串进行正则匹配,返回匹配结果。匹配成功返回一个数组,匹配失败返回null。带有g修饰符,会一次性返回所有匹配成功的结果。

4.2 String.prototype.search()

返回第一个满足条件的匹配结果在整个字符串中的位置。如果没有任何匹配,则返回-1

4.3 String.prototype.replace()

4.3.1 替换匹配的值。它接受两个参数,第一个是正则表达式,表示搜索模式,第二个是替换的内容。

g修饰符,替换所有匹配成功的值。否则只替换第一个匹配成功的值。

应用,就是消除字符串两端空格:

var str = '  xxxxxxx  ';

str.replace(/^s+|s+$/g, '')

4.3.2 replace方法的第二个参数可以使用$符号代替

  • $&:匹配的子字符串。
  • $`:匹配结果前面的文本。
  • $’:匹配结果后面的文本。
  • $n:匹配成功的第n组内容,n是从1开始的自然数。
  • $$:指代美元符号$
'hello world'.replace(/(w+)s(w+)/, '$2 $1')
// "world hello"

'abc'.replace('b', '[$`-$&-$']')
// "a[a-b-c]c"

4.3.3 replace方法的第二个参数还可以是一个函数,将每一个匹配内容替换为函数返回值。

'3 and 5'.replace(/[0-9]+/g, function (match) {
  return 2 * match;
})
// "6 and 10"

作为replace方法第二个参数的替换函数,可以接受多个参数。其中,第一个参数是捕捉到的内容,第二个参数是捕捉到的组匹配(有多少个组匹配,就有多少个对应的参数)。此外,最后还可以添加两个参数,倒数第二个参数是捕捉到的内容在整个字符串中的位置(比如从第五个位置开始),最后一个参数是原字符串。下面是一个网页模板替换的例子。

4.4 String.prototype.split()

按照正则规则分割字符串,返回一个由分割后的各个部分组成的数组。

// 非正则分隔
'a,  b,c, d'.split(',')
// [ 'a', '  b', 'c', ' d' ]

// 正则分隔,去除多余的空格
'a,  b,c, d'.split(/, */)
// [ 'a', 'b', 'c', 'd' ]

// 指定返回数组的最大成员
'a,  b,c, d'.split(/, */, 2)
[ 'a', 'b' ]

贪婪匹配:

// 例一
'aaa*a*'.split(/a*/)
// [ '', '*', '*' ]

// 例二
'aaa**a*'.split(/a*/)
// ["", "*", "*", "*"]

如果正则表达式带有括号,则括号匹配的部分也会作为数组成员返回:

'aaa*a*'.split(/(a*)/)
// [ '', 'aaa', '*', 'a', '*' ]

5. 匹配规则

5.1 元字符

  • 点字符(.) :匹配除回车(r)、换行(n) 、行分隔符(u2028)和段分隔符(u2029)以外的所有字符。
  • 位置字符^ 表示字符串的开始位置,$ 表示字符串的结束位置。
  • 选择符(|):表示“或关系”(OR),即cat|dog表示匹配catdog

5.2 转义符

正则表达式中那些有特殊含义的元字符,如果要匹配它们本身,就需要在它们前面要加上反斜杠。

正则表达式中,需要反斜杠转义的,一共有12个字符:^.[$()|*+?{

如果使用RegExp方法生成正则对象,转义需要使用两个斜杠,因为字符串内部会先转义一次。

(new RegExp('1+1')).test('1+1')
// false

(new RegExp('1+1')).test('1+1')
// true

5.3 特殊字符

  • cX 表示Ctrl-[X],其中的X是A-Z之中任一个英文字母,用来匹配控制字符。
  • [b] 匹配退格键(U+0008),不要与b混淆。
  • n 匹配换行键。
  • r 匹配回车键。
  • t 匹配制表符 tab(U+0009)。
  • v 匹配垂直制表符(U+000B)。
  • f 匹配换页符(U+000C)。
  • 0 匹配null字符(U+0000)。
  • xhh 匹配一个以两位十六进制数(x00-xFF)表示的字符。
  • uhhhh 匹配一个以四位十六进制数(u0000-uFFFF)表示的 Unicode 字符。

5.4 预定义模式

  • d 匹配0-9之间的任一数字,相当于[0-9]
  • D 匹配所有0-9以外的字符,相当于[^0-9]
  • w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]
  • W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]
  • s 匹配空格(包括换行符、制表符、空格符等),相等于[ trnvf]
  • S 匹配非空格的字符,相当于[^ trnvf]
  • b 匹配词的边界。
  • B 匹配非词边界,即在词的内部。

5.5 字符类

表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内,比如[xyz]表示xyz之中任选一个匹配。

5.5.1 脱字符(^)

如果方括号内的第一个字符(脱字符只有在字符类的第一个位置才有特殊含义,否则就是字面含义)是[^],则表示除了字符类之中的字符,其他字符都可以匹配。比如,[^xyz]表示除了xyz之外都可以匹配。

如果方括号内没有其他字符,即只有[^],就表示匹配一切字符,其中包括换行符。相比之下,点号作为元字符(.)是不包括换行符的。

var s = 'Please yesnmake my day!';

s.match(/yes.*day/) // null
s.match(/yes[^]*day/) // [ 'yesnmake my day']

5.5.2 连字符(-)

对于连续序列的字符,连字符(-)用来提供简写形式,表示字符的连续范围。比如,[abc]可以写成[a-c][0123456789]可以写成[0-9],同理[A-Z]表示26个大写字母。

由于存在ASCII编码顺序和常识顺序相悖的情况,不建议使用 -

5.6 重复类

模式的精确匹配次数,使用大括号({})表示。{n}表示恰好重复n次,{n,}表示至少重复n次,{n,m}表示重复不少于n次,不多于m次。

/lo{2}k/.test('look') // true
/lo{2,5}k/.test('looook') // true

5.7 量词符

  • ? 问号表示某个模式出现0次或1次,等同于{0, 1}
  • * 星号表示某个模式出现0次或多次,等同于{0,}
  • + 加号表示某个模式出现1次或多次,等同于{1,}

5.8 贪婪模式

上一小节的三个量词符,默认情况下都是最大可能匹配,即匹配直到下一个字符不满足匹配规则为止。这被称为贪婪模式。

var s = 'aaa';
s.match(/a+/) // ["aaa"]

上面代码中,模式是/a+/,表示匹配1个a或多个a,那么到底会匹配几个a呢?因为默认是贪婪模式,会一直匹配到字符a不出现为止,所以匹配结果是3个a

如果想将贪婪模式改为非贪婪模式,可以在量词符后面加一个问号。

var s = 'aaa';
s.match(/a+?/) // ["a"]

5.9 组匹配

5.9.1 概述

正则表达式的括号表示分组匹配,括号中的模式可以用来匹配分组的内容。

/fred+/.test('fredd') // true
/(fred)+/.test('fredfred') // true

上面代码中,第一个模式没有括号,结果+只表示重复字母d,第二个模式有括号,结果+就表示匹配fred这个词。

正则表达式内部,还可以用n引用括号匹配的内容,n是从1开始的自然数,表示对应顺序的括号。

var tagName = /<([^>]+)>[^<]*</1>/;

tagName.exec("<b>bold</b>")[1]
// 'b'

上面代码中,圆括号匹配尖括号之中的标签,而1就表示对应的闭合标签。

5.9.2 非捕获组

(?:x)称为非捕获组(Non-capturing group),表示不返回该组匹配的内容,即匹配的结果中不计入这个括号。

var m = 'abc'.match(/(?:.)b(.)/);
m // ["abc", "c"]
// 正常匹配
var url = /(http|ftp)://([^/rn]+)(/[^rn]*)?/;



url.exec('http://google.com/');
// ["http://google.com/", "http", "google.com", "/"]

// 非捕获组匹配
var url = /(?:http|ftp)://([^/rn]+)(/[^rn]*)?/;

url.exec('http://google.com/');
// ["http://google.com/", "google.com", "/"]

5.9.2 先行断言

x(?=y)称为先行断言(Positive look-ahead),x只有在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟着百分号的数字,可以写成/d+(?=%)/

“先行断言”中,括号里的部分是不会返回的。

var m = 'abc'.match(/b(?=c)/);
m // ["b"]

5.9.3 先行否定断言

x(?!y)称为先行否定断言(Negative look-ahead),x只有不在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟的不是百分号的数字,就要写成/d+(?!%)/

/d+(?!.)/.exec('3.14')
// ["14"]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值