吃透js中正则表达式
栏目: JavaScript · 发布时间: 5年前
内容简介:我们在开发的过程中总会碰到一些需求需要做字符串匹配,当遇到一些稍微复杂一点的匹配规则时,如果我们对正则还不那么清晰,我们总是会去网上搜索一些现成的正则匹配,ctrl+c,ctrl+v。时间长了我们对这种修修补补的方式不厌其烦。那么今天就对正则表达式做足功夫,磨刀不误砍柴工,首先推荐一个学习正则的一个可视化的工具网址:regexper.com,输入正则规则即可生成匹配规则的流程图。了解并吃透正则会为我们以后开发节省很多时间和精力,一劳永逸。先从最基本的概念开始吧,let go!概念:有特殊含义的特殊字符,eg
我们在开发的过程中总会碰到一些需求需要做字符串匹配,当遇到一些稍微复杂一点的匹配规则时,如果我们对正则还不那么清晰,我们总是会去网上搜索一些现成的正则匹配,ctrl+c,ctrl+v。时间长了我们对这种修修补补的方式不厌其烦。那么今天就对正则表达式做足功夫,磨刀不误砍柴工,首先推荐一个学习正则的一个可视化的 工具 网址:regexper.com,输入正则规则即可生成匹配规则的流程图。了解并吃透正则会为我们以后开发节省很多时间和精力,一劳永逸。先从最基本的概念开始吧,let go!
元字符
概念:有特殊含义的特殊字符,eg: * + ? $ ^ . | \ ( ) { } [ ]等
通用含义元字符
在大部分语言语境中代表同一种含义,如下表:
字符 | 含义 |
---|---|
\t | 水平制表符 |
\v | 垂直制表符 |
\n | 换行符 |
\r | 回车符 |
\0 | 空字符 |
\f | 换页符 |
\cX | Ctrl+X |
其他含义元字符
1. 字符类
- 我们可以使用元字符[]来构建一个简单的字符类
- 所谓的类是指符合某些特性的对象,一个泛指,而不是特指某个字符
- 表达式[abc]归为一类,表达式可以匹配这些类的字符
2. 字符类取反
- 我们可以使用元字符^来创建反向类/负向类
- 反向类的意思是不属于某个类的内容
- 表达式[^abc]表示不是字符a或b或c的内容
3. 范围类
- 正则表达式还提供了范围类
- 我们使用[a-z]来连接两个字符表示从a到z的任意字符
- 这是个闭区间也就包含a和z本身
4. 预定义类
- 正则表达式提供了一些特殊字符表示自一组比较复杂的匹配规则,如下表:
字符 | 等价 | 含义 |
---|---|---|
. | [^\r\n] | 除了回车符和换行符之外的所有字符 |
\d | [0-9] | 数字字符 |
\D | [^0-9] | 非数字字符 |
\s | [\t\n\x0B\f\r] | 空白符 |
\0 | [^\t\n\x0B\f\r] | 非空白符 |
\w | [a-zA-Z_0-9] | 单词字符(字母数字下划线) |
\W | [^a-zA-Z_0-9] | 非单词字符 |
5. 边界
- 正则表达式还提供了几个常用的边界匹配字符,如下表:
字符 | 含义 |
---|---|
^ | 以xxx开始 |
$ | 以xxx结束 |
\b | 单词边界 |
\B | 非单词边界 |
6. 量词
字符 | 含义 |
---|---|
? | 出现一次或0次(最多出现一次) |
+ | 出现一次或多次(最少出现一次) |
* | 出现0次或多次(任意次) |
{n} | 出现n次 |
{n, m} | 出现n到m次 |
{n, } | 至少出现n次 |
js正则的贪婪模式和非贪婪模式
- 贪婪模式:\d{3,6}匹配数字3到6次,那么在匹配的过程中会尽可能多的的匹配。如:
'12345678'.replace(/\d{3,6}/, 'X') // "X78" 复制代码
- 非贪婪模式:在量词后面加上 ? ,可以让正则表达式尽可能少的匹配,也就是非贪婪模式。
'12345678'.replace(/\d{3,6}?/, 'X') // "X45678" 复制代码
分组
对一组正则规则加(),可以对正则进行分组,
比如:对taoyouyou这组单词匹配三次 taoyouyou{3}
可视化后能看到只是最后一个单词u重复了3次,并没有达到目的 (taoyouyou){3}
taoyouyou重复了3次
反向引用
例如实现2019-02-22 => 02/22/2019的转化。
'2019-02-22'.replace(/(\d{4})-(\d{2})-(\d{2})/,'$2/$3/$1') // "02/22/2019" 复制代码
忽略分组
不需要捕获某些分组只需要在分组内加 ?: 就可以了。 (?:taoyouyou).(ok)
前瞻
- 正则表达式从文本头部向尾部解析,文本尾部方向称为 “前”
- 前瞻:正则表达式匹配到规则的时候,向前检查是否符合断言,后顾/后瞻方向相反
- JavaScript不支持后顾
- 符合和不符合某项断言称为肯定/正向匹配和否定/负向匹配
名称 | 正则 | 含义 |
---|---|---|
正向前瞻 | exp(?=assert) | |
负向前瞻 | exp(?!assert) | |
正向后顾 | exp(?<=assert) | JavaScript不支持 |
负向后顾 | exp(?<!assert) | JavaScript不支持 |
正则对象属性
- global: 是否全文匹配,默认false,匹配规则后面加g开启
- ignoreCase: 是否大小写敏感, 默认false,匹配规则后面加i开启
- multiline: 多行搜索, 默认false,匹配规则后面加m开启
- lastIndex: 当前表达式匹配内容最后一个字符的下一个位置
- source: 正则表达式的文本字符串 这几个属性都是只读属性
reg=/\d/gmi reg.global // true reg.ignoreCase // true reg.multiline // true reg.lastIndex // 0 reg.source // "\d" 复制代码
对象方法
1. 正则test方法
RegExp.prototype.test(str)
- 用于测试字符串参数中是否存在匹配正则表达式模式的字符串
- 如果存在则返回true,否则返回false
var reg2=/\w/g; 进行reg2.test('ab')时,第三次会变成false 原因:while(reg2.test('ab')){ console.log(reg2.lastIndex); } 即进行test时,正则表达式的lastIndex会发生变化 输出:1 2 表示第一个匹配上了、第二个匹配上了
2. 正则exec方法
RegExp.prototype.exec(str)
- 使用正则表达式模式对字符串参数进行匹配搜索,并将更新全局对象属性以反映匹配结果
- 如果没有匹配则返回null,否则返回一个结果数组: 属性index(声明匹配文本的第一个字符的位置), input(存放被检索的字符串string) 数组本身: [与正则表达式相匹配的文本,与正则对象的第一个子表达式(分组)相匹配的文本, 与正则对象的第二个子表达式(分组)相匹配的文本,…… ]
var reg3=/\d(\w)(\w)\d/; // 非全局搜索只能匹配到第一个结果 var reg4=/\d(\w)(\w)\d/g; // 全局搜索匹配全文 var ts = '$1az2bb3cy4dd5ee' var ret1= reg3.exec(ts) // (3) ["1az2", "a", "z", index: 1, input: "$1az2bb3cy4dd5ee", groups: undefined] console.log(reg3.lastIndex+'\t'+ret1.index+'\t'+ret1.toString()) // "0 1 1az2, a, z" while(ret2 = reg4.exec(ts)){ console.log(reg4.lastIndex+'\t'+ret2.index+'\t'+ret2.toString()) } // "5 1 1az2, a, z" // "11 7 1az2, a, z" 复制代码
3. 字符串对象search方法
String.prototype.search(reg)
- search方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串
- 返回第一个匹配结果index,查不到返回-1
- search()不执行全局匹配,它将忽略标志g, 并总是从字符串的开始进行检索
4. 字符串对象match方法
String.prototype.match(reg)
- match方法将检索字符串,以找到一个或多个与regexp相匹配的字符串
- regexp是否具有标志g对结果影响很大
非全局调用
- 返回数组的第一个元素存放的是匹配文本,而其余的元素存放的是与正则表达式的子表达式匹配的文本
- 除了常规的数组元素之外,返回的数组还含有2个对象属性:index声明匹配文本的起始字符在字符串的位置,input声明对stringObject的引用
- 全局调用的返回与正则表达式的exec方法相类似,即:[与正则表达式相匹配的文本,与正则对象的第一个子表达式(分组)相匹配的文本, 与正则对象的第二个子表达式(分组)相匹配的文本,…… ],数组有index和input属性
全局调用
- 如果regexp具有标志g则match方法将执行全局检索,找到字符串中的所有匹配子字符串
- 没有找到任何匹配的子串,则返回null
- 如果找到了一个或多个匹配子串,则返回-一个数组
- 数组元素中存放的是字符串中所有的匹配子串,而且也没有index属性或input属性
var reg3=/\d(\w)(\w)\d/; // 非全局搜索只能匹配到第一个结果 var reg4=/\d(\w)(\w)\d/g; // 全局搜索匹配全文 var ts = '$1az2bb3cy4dd5ee' var ret1= ts.match(reg3) // (3) ["1az2", "a", "z", index: 1, input: "$1az2bb3cy4dd5ee", groups: undefined] console.log(reg3.lastIndex+'\t'+ret1.index) // 0, 1 var ret2 = ts.match(reg4) // (2) ["1az2", "3cy4"] console.log(reg4.lastIndex+'\t'+ret2.index) // 0 undefined 复制代码
5. 字符串对象split方法
String.prototype.split(reg)
- 我们经常使用split方法把字符串分割为字符数组 eg: 'a,b,c,d'.split(','); //["a", "b", "c", "d"]
- 在一些复杂的分割情况下我们可以使用正则表达式解决 eg: 'alb2c3d'.split(/\d/; //["a", "b", "c", "d"]
6. 字符串对象replace方法
String.prototype.replace
- String.prototype.replace(str, replaceStr)
- String.prototype.replace(reg, replaceStr)
- String.prototype.replace(reg, function) function参数含义 function会在每次匹配替换的时候调用,有四个参数 1、匹配字符串 2、正则表达式分组内容,没有分组则没有该参数 3、匹配项在字符串中的index 4、原字符串
'a1b2c3d4e5'.replace(/\d/g, function(match, index, origin){ return parseInt(match) + 1; }) // "a2b3c4d5e6" 'a1b2c3d4e5'.replace(/(\d)(\w)(\d)/g, function(match, group1, group2, group3, index, origin){ console.log(match) return group1 + group3; }) // 1b2 // 3d4 // "a12c34e5" 复制代码
原文地址:taoyouyou.gitee.io
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。