Web前端之路让前端飞Web 前端开发

Javascript中的正则表达式——初识正则

2017-10-14  本文已影响42人  ac68882199a1

今天的这篇是补更的上周的内容,对于几乎迟到了整整一周的这件事,我感到很惭愧,因为自己没能很好的平衡工作和个人事务之间的关系。废话不多说,下面进入正题

很多语言中都有对正则表达式的支持,javascript 也不例外。虽然我们经常听说正则,但是实际使用中却很少回去使用,原因无他——不会。所以今天我们就一起来认识一下正则表达式

什么是正则表达式(Regular Expression)?
使用单个字符串来描述、匹配某种规则的字符串

正则表达式

正则表达式由两种基本字符类型组成:原意文本字符和元字符

元字符是在正则表达式中含有特殊含义的非字母字符,如:

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

当然,元字符并不止上面这些,还有 \t \b 等等

字符类

在正则中的一个字符对应着字符串中的一个字符,如:

ab\t
=> ab // 最后一个为 tab 水平制表符

但是往往我们需要表示的并不只是单独的一个字符,而可能是一类具有某种特征的字符,这时可以通过构建一个字符类来达到目的

[abc] // [abc] 为一个整体,只对应字符串中的一个字符
=> a 
=> b
=> c

上面的例子就通过构建了一个 [abc]字符类达到了匹配 abc 的目的

如果要不匹配某一类字符的话,可以在中括号内的最前面添加 ^ 来达到取反的目的

[^abc] // 不匹配 a 或 b 或 c

范围类

如果我们需要匹配一个数字,使用字符类可能会这样写 [0123456789] ,但是通过范围类可以达到很简单的书写方式

[0-9] // 匹配数字
[a-z] // 匹配小写英文字母
[a-zA-Z] // 匹配所有英文字母

范围类本身是一个闭区间,包括了范围的两头;同时也可以通过连写达到其他的匹配目的

但是-本身并不是特殊字符,只有在两个文本字符之间时才能有表示范围的作用。那如果我们需要匹配-该怎么办呢?

[0-9-] // 在最后加上 - ,从而达到匹配 0123456789- 的目的

预定义类

对于常用的范围类,正则为我们提供了一些同样作用的预定义类,如 [0-9] 等价于 \d ,常用的有以下这些:

. => [^\r\n] // 除回车和换行符之外的所有字符
\d => [0-9] // 所有数字
\D => [^0-9] // 所有非数字
\s => [\t\nx0B\f\r] // 空白符
\S => [^\t\nx0B\f\r] // 非空白符
\w => [a-zA-Z_0-9] // 单词字符(字母数字下划线)
\W => [^a-zA-Z_0-9] // 非单词字符

边界匹配

^ // 以xxx开始 (在中括号中表示取反)
$ // 以xxx结束
\b // 单词边界
\B // 非单词边界

举例说明:

^ac\d
// 匹配以 a 开头,第二个字符为 c,第三个字符为数字的字符串,如 ac0 ac1r ac2fds 的前3个字符将会被匹配
// bc0d ba13fsd b0adas 等将不会被匹配

\di9$
// 匹配以 9 结尾,倒数第二个字符为 i,倒数第三个字符为数字的字符串,如 das0i9 12i9 r324i9 的最后3个字符将会被匹配

\bf\dk\b
// 只匹配以 f 开头 k 结尾 中间是数字的三位字符串 f0k f1k f2k
// af1k f1k3 f9i 等将不会被匹配

\bf\dk\B
// 只匹配以 f 开头,中间是数字,第三位是 k 且 k 不是结尾的字符串 f0k1 f0kkk f2k22
// f0k f1k f2k fkk fkf fkk0 等将不会被匹配

量词

如果需要匹配一个十位数字,可能会这样写

\d\d\d\d\d\d\d\d\d\d

但也可以像下面这样写

\d{10}

{10} 就是一个量词描述

量词有下面这些

? // 最多出现一次 a?
+ // 最少出现一次 a+
* // 出现任意次 a*
{n} // 出现 n 次 a{3}
{n,m} // 出现 n 到 m 次 a{1,3}
{n,} // 至少出现 n 次 a{2,}
// 不存在 {,m} 的写法,它等同于 {0,m}

贪婪模式与非贪婪模式

如果有字符串12345678,有正则\d{3,6},那么它会如何匹配呢?

正则在匹配的时候回尽可能多的匹配,所以上面的这个正则只会匹配到12345678将不会被匹配,这叫正则表达式的贪婪模式

如果我们想要正则只要匹配到就不在继续匹配,就要使用正则的非贪婪模式,只需要在两次的后面加上?就可以了

// 非贪婪模式的正则
\d{3,6}?

// 0123456789 这个字符串将会被匹配到 012 345 678

分组

当有一个单子需要被重复5次时,我们会这样写word{5},但是这个正则对应的字符串应该是worddddd,量词只会将它紧邻的字符重复

所以如果要重复一个整体,就需要将word作为一个整体:

(word){5}
// wordwordwordwordword

通过()我们可以达到分组的目的

再举例:单词+数字连续重复3次

([a-zA-Z]\d){3}
// a3f4d2
// j9k0l8

需要表示 word 或 number 这两个英文单词时,可以通过|来表示

(word)|(number)
// word
// number
// 需要注意的是不能写成 word|number 否则会匹配 wordumber 或者 wornumber

反向引用

当我们匹配一个字符串时,可能会需要获取原字符串中的内容,此时我们可以这样做

// 原字符串
2017-10-14

// 正则
(\d{4})-(\d{2})-(\d{2})

// 需要转换成 10/14/2017 的格式,反向引用的表达式
$2/$3/$1

在正则中被分组的字符,我们可以按顺序通过 $1 $2 $3 ... 来捕获,如果需要引用原字符串的内容,只需要引用对应的 $1 $2 $3 ... 即可

如果分组后不想捕获,可以忽略分组,只需要在分组内加上?:即可

(\d{4})-(?:\d{2})-(\d{2})

// 中间的第二个分组将会被忽略,原先的 $2 现在会获取到原先 $3 对应的值

前瞻后顾

正则在匹配到规则的时候,向前检查是否符合断言叫前瞻,向后检查则叫后顾

文本的尾部为前,头部为后

其中 js 不支持后顾

符合肯定断言叫正向匹配,不符合叫负向匹配

// assert 为断言正则

// 正向前瞻
exp(?=assert)
//负向前瞻
exp(?!assert)

//正向后顾
exp(?<=assert)

//负向后顾
exp(?<!assert)

前瞻后顾不会被匹配,它只是作为是否匹配成功的一个条件

\w(?=\d)
// 匹配一个单词字符,如果这个字符后面是一个数字,则这个字符匹配成功,否则失败
// a1 匹配到 a
// _0 匹配到 _
// a2b3 匹配到 a b
// *0 由于第一个字符不是单词字符,匹配失败
// aa 由于第二个字符不是数字,匹配失败

正则表达式的学习可以有厚厚的一本书,如果想要深入学习正则的话,本篇文章的这点内容肯定是不够的
但是作为提升我们平时开发效率的工具而言,掌握住上面这些也基本够用了
下一篇(明天)我们来一起学习在 javascript 中如何使用正则表达式

扫码关注前端周记公众号
上一篇下一篇

猜你喜欢

热点阅读