对于正则的使用只在 python 中使用过…
对于 JavaScript 中的正则认知一直保留在'它是一个对象'上。
所以打算正式的学一学。
创建正则表达式
包含在斜杠之间
1 | const regex = /ab+c/ |
当正则表达不会变动时 建议采用此方法
调用RegExp对象的构造函数
1 | //可以直接使用字符串 |
当正则表达会变动时,如由用户输入、模式会改变等 建议采用此方法
正则修饰符(标志)
JavaScript 的正则表达式有修饰符的使用,相比 python 的正则来说用法差异还是有点大的。
JavaScript 的正则修饰符( mdn 中称为标志) 有:
- g / i / m 这三个较为常用
- y / u 是在 ES6 中新增修饰符
- 还有一些其他的,比如 s / U / x / A 等
g
global 全局搜索,就是说不会匹配到一个匹配项之后就停止,而是一直匹配到输入的结束。
i
ignore 大小写不敏感。
m
more 允许多行搜索。
y
ES6 新增修饰符 参考博客
执行'粘性'搜索,匹配从目标字符串的当前位置开始,可以使用 y 标志。( ← MDN 中的描述,但是看不太懂
y 修饰符的作用与 g 修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g 修饰符只要剩余位置中存在匹配就可,而 y 修饰符确保匹配必须从剩余的第一个位置开始,这也就是'粘连'的含义。 ( ← 博客中的说法,get!
其实两种说法都有一定理解难度,所以遇事不决举个栗子。
1 | //匹配用字符串 |
上面的例子中的 null 原因就是第一次匹配之后剩下的字符为 '_123' 而粘性搜索要求匹配必须在剩余字符串首,所以只有当且仅当剩下的字符为 '123α'( α 为任意数量的任意字符)才会匹配到
u
ES6 新增修饰符 参考博客
u (小写,和大写的 U 是不同的)这个修饰符在 MDN 中文文档里没有提到。但是之前在阮一峰的 《ES6 标准入门》里看到过。
u 指的是 'unicode' , 用于处理大于 \uFFFF 的 Unicode 字符(就是四个字符的 UTF-16 编码
(说起来从来没有用到过 utf-16 的字符
那么遇事不决举个参考博客中的栗子:
1 | const R1 = new RegExp(/^\uD83D/) |
可以看到 R2 的检测结果是 false 因为 \uD8F2\uDc2A 是一个四字节的 UTF-16 编码,在加了 u 修饰符之后会把 \uD8F2\uDc2A 识别为一整个字符。
正则的特殊符号
字符 | 含义 |
---|---|
\ | 1. 用于转义 2.后接字母表示特殊含义如 \b, \d 等 |
^ | 匹配输入的开始。如果多行标志被设置为true,那么也匹配换行符后紧跟的位置。 举个例子: \^demo\ 与以'demo'开头的文本匹配,如'demonstrate' 可以匹配 但是'this is a demo' 不行 |
$ | 和 ^ 作用类似。区别在于 $ 用于匹配输入的结束。如果多行标示被设置为true,那么也匹配换行符前的位置。在 ^ 的例子中,若是 \demo$\ 则 'demonstrate' 不行 但是'this is a demo' 可以 |
* | 匹配前一表达式0次或多次 举个例子:/bo*/会匹配 'A ghost boooooed' 中的 ‘booooo’ 和 'A bird warbled' 中的 ‘b’ |
+ | 匹配前一表达式1次或多次 |
? | 1. 匹配前一表达式0次或1次 2. 如果紧跟在任何量词 *、 +、? 或 {} 的后面,将会使量词变为非贪婪的 举个例子:对 '123abc' 应用 /\d+/ 将会返回 '123',如果使用 /\d+?/,那么就只会匹配到 '1'。 3.先行断言 |
. | 匹配换行符之外的任意字符 |
( ) | 参考博客 1.用于限定量词范围,例如/(demo)?/匹配0或多个'demo' 2. 捕获功能 |
\x | 'x' 是数字。返回最后的第n个子捕获匹配的子字符串(捕获的数目以左括号计数) |
(?:x) | 匹配 'x' 但是不记住匹配项。上面一行的博客中也有有提到,只分组不捕获 |
(? |
比普通的分组多了 |
x(?=y) | 匹配'x'仅仅当'x'后面跟着'y'.称为先行断言。告诉正则表达式继续向后看一些字符但是并不移动位置(就是说不匹配y) |
(?<=y)x | 匹配'x'仅仅当'x'前面是'y'.称为后行断言。 |
x(?!y) | 匹配'x'仅仅当'x'后面不跟着'y',称为正向否定查找。 |
x|y | 匹配'x'或'y' |
{n} | n是一个正整数,匹配了前面一个字符刚好发生了n次。 举个例子:/a{2}/不会匹配'candy'中的'a',但是会匹配'caandy'中所有的'a',以及'caaandy'中的前两个'a' |
{n,m} | n 和 m 都是整数。匹配前面的字符至少 n 次,最多 m 次。如果 n 或者 m 的值是0, 这个值被忽略。 |
[xyz] | 一个字符集合。匹配方括号中的任意字符。可以使用 - 进行指定字符范围。 |
[^xyz] | 一个反向字符集。也就是说, 它匹配任何没有包含在方括号中的字符。 |
[\b] | 匹配退格 |
\b | 匹配单词边界。一个词的边界就是一个词不被另外一个'字'字符跟随的位置或者没有其他'字'字符在其前面的位置。(狗屎这个看不懂啊!)。换个网搜的说法:如果字符的左右两边有空白字符则为单词边界 |
\B | 匹配非单词边界。字符左右两边没有空白字符就是非单词边界 |
\d | 匹配一个数字,等于[0-9] |
\D | 匹配一个非数字,等于[^0-9] |
\f | 匹配换页符 |
\n | 匹配换行符 |
\r | 匹配回车符 |
\t | 匹配一个水平制表符 |
\v | 匹配一个垂直制表符 |
\s | 匹配一个空白字符,包括空格、制表符、换页符和换行符。 |
\S | 匹配一个非空白字符 |
\w | 匹配一个字母、数字或者下划线,等价于[A-Za-z0-9_] |
\W | 匹配一个非字母、数字或者下划线,等价于[^A-Za-z0-9_] |
QAQ 好多啊
正则表达式的使用 (应用)
匹配出来总要用的嘛!
使用正则表达式的方法这里分为两类,一类是 RegExp 的方法,另一类是 String 的方法。
RegExp 的方法
有两个,在上面的 보기 中有使用到。
一个是 exec( ) 另一个是 test( )
RegExp.exec( )
参数: 字符串
返回值: 数组 or null
当且仅当没有匹配结果时返回 null 。
有匹配结果时,数组的第一元素为匹配到的文本,紧跟的元素是用 ( ) 捕获的内容,之后的元素是 index 属性,为匹配到的文本在源字符串中的下标,再之后的元素为 input 属性,保存源字符串,最后会有一个 groups 属性,好像是 ES6 新增的,用于存储对捕获分组的内容。
举个例子:
1 | const rDate = /(?<year>\d{4})-(?<month>\d{2})-(?<date>\d{2})/ |
RegExp.test( )
判断一个模式是否存在于某个字符串中。
参数: 字符串
返回值: true or false
하지만!
当 RegExp 设置了全局标志,test( ) 的执行也(为什么是'也'呢?因为其实 exec( ) 也会,但是为什么上面没有提到呢? 因为懒,不想回去填坑了呜呜呜)会改变 RegExp 的 lastIndex 值。后续的执行会从 lastIndex 处开始匹配。(RegExp.exec( )同理)
来来来,遇事不决举个栗子:
1 | const R = /\d/g |
String 的方法
啊 这个就比较多了(感觉更常用
- str.match( )
- str.search( )
- str.replace( )
- str.split( )
str.match( )
参数:RegExp | 非 RegExp 对象的对象 | 空
返回值:数组 | null
使用了 g 修饰符,则没有匹配内容时,返回 null ,有匹配内容时,返回匹配内容的数组
如果未使用 g 修饰符,则返回第一个匹配项的信息及补捕获组,和 RegExp.exec( ) 的返回值一样(就是说不含 g 标志时,str.match( ) 和 RegExp.exec( ) 一致
举个例子:
1 | let a = 'no number' |
拓展一下上面例子的应用。
1 | const GROUPS = '2019-06-17'.match(/(?<year>\d{4})-(?<month>\d{2})-(?<date>\d{2})/).groups |
当传的参数为空时,返回值为包含一个空字符串的数组 [“”]
当参数为非正则表达式对象 str.match(obj) 。会先调用 new RegExp(obj) 隐式的转化成一个 RegExp
再举个例子:
1 | "i don't know".match('do') |
str.search( )
参数: RegExp 对象 | 非 RegExp 对象的对象 |
返回值: 匹配成功则返回第一个匹配项的下标 | 匹配失败则返回 -1
和 str.indexOf( ) 很像ㄟ 。
区别在于 indexOf( ) 的参数为 searchValue '搜索的目标子字符串' 和 fromIndex '从 fromIndex 这个位置开始搜索'
相似点的 indexOf( ) & search( ) 都是大小写敏感的。
当输入的参数为非 RegExp 对象的对象时,进行的处理与 str.match( ) 一致。
功能与 RegExp.test( ) 类似。
하지만!
需要注意的是 str.search( ) 无视 g 修饰符和 RegExp 对象的 lastIndex 属性, 返回值总是第一个匹配到的匹配项的下标或者 -1 。、
str.replace( )
参数: RegExp | SubStr, newSubStr | function
- RegExp 对象,该正则匹配到的内容会被第二个参数(或其返回值)替换。
- SubStr,将被替换掉的字符串,仅第一个匹配项会被替换。
- newSubStr,用于替换第一个参数匹配到的结果。
- function,用于创建新子字符串的函数,函数的返回值将替换掉第一个参数匹配到的结果。
返回值:替换完成的新字符串。
newSubStr中可以使用特殊变量
- $$ 插入一个'$', 类似于\\ ;
- $& 插入匹配的子串 例如 str.replace(RegExp,’$&’) 不会发生任何变化;
- $` 插入匹配项的左边的内容;
- $’ 插入匹配项的右边的内容;
- $n 假如第一个参数是 RegExp对象,并且 n 是个小于100的非负整数,那么插入第 n 个括号匹配的字符串,n 从 1 开始。
function
当第一个参数为 RegExp 且使用了 g 修饰符时,每次匹配都会调用 function 。
函数的参数:
- match 匹配的子串,类似于上面的 $&
- p1,p2… 类似于上面的$1,$2…
- offset 匹配到的自字符在原字符串中的偏移量
- string 原字符串。
str.split( )
最后一个了!最后一个了!
参数: [separator[, limit]]
- separator 指定表示每个拆分应发生的点的字符串。可以是 str 也可以是 RegExp。
- limit 整数,限定返回的分割片段数量。
返回值: 分隔好的数组
举两个 MDN 中的例子:
1 | // example 1 : |
总结
那就差不多是这样了。
以怎么定义、有哪些内容、怎么使用三个方面来搞了一下 JavaScript 的正则。
内容还是好多的啊,尤其是特殊符号里内容贼多,但是其实常用的也就那么一些。
整体感觉就是和 css 的 animation 一样,明明就一个东西却能玩出花来。
好啦那么
祝大家新年快乐