对于这些均可以使用正则表达式完成。若是你还不知道该怎么用,那有必要学习下正则表达式了。javascript
正则表达式专门用于描述字符串的字符组合格式。咱们常常对字符串判断是否匹配指定的正则表达式,以及对匹配的字符进行操做(如替换,转换等)。html
RegExp用来表示正则表达式。RegExp便是构造函数也是个工厂函数。
建立正则表达式的方式:java
// 字面量方式 /pattern/flags // 构造函数方式 new RegExp(pattern [, flags]) // 工厂函数方式 RegExp(pattern [, flags])
对指定对字符串进行一次正则匹配操做。若是匹配成功则返回一个数组,不然返回null。
返回的数组:正则表达式
该数组被添加了两个额外属性:
3.1 inputexpress
表示输入原始字符串,即exec方法的实参。
3.2 indexc#
表示匹配的字符串在输入参数的下标位置。
// matchs1为["ab", "b", index: 0, input: "abcabc"] var matchs1 = /a(b)/.exec('abcabc'); // 捕获分组 // matchs2为["ab", index: 0, input: "abcabc"] var matchs2 = /ab/.exec('abcabc');
判断指定的字符串是否匹配正则表达式。数组
控制匹配行为。安全
表示正则表达式下次执行匹配操做时字符串下标位置。ruby
var r = /a(b)/g; console.log(r.lastIndex); // 0 r.test('abcabc'); //true, 从字符串下标0开始匹配 console.log(r.lastIndex); // 2 r.test('abcabc'); //true, 从字符串下标2开始匹配 console.log(r.lastIndex); // 5
注意几点:函数
只有指定全局匹配m时,lastIndex才有效,不然一直为0;
var r = /a(b)/; // 没有指定全局m console.log(r.lastIndex); // 0 r.test('abcabc'); //true, 从字符串下标0开始匹配 console.log(r.lastIndex); // 0 r.test('abcabc'); //true, 从字符串下标0开始匹配 console.log(r.lastIndex); // 0
每次执行全局模式匹配(经过exec或者test方法)时都会影响lastIndex的值。
注意下例中屡次调用会出现匹配失败的状况:
var r = /a(b)/g; console.log(r.lastIndex); // 0 r.test('abcabc'); //true, 从字符串下标0开始匹配 console.log(r.lastIndex); // 2 r.test('abcabc'); //true, 从字符串下标2开始匹配 console.log(r.lastIndex); // 5 r.test('abcabc'); //false, 从字符串下标5开始匹配 console.log(r.lastIndex); // 0,下次🈶️从头开始匹配了
lastIndex属性是可读写的。
var r = /a(b)/g; console.log(r.lastIndex); // 0 r.test('abcabc'); //true, 从字符串下标0开始匹配 console.log(r.lastIndex); // 2 r.test('abcabc'); //true, 从字符串下标2开始匹配 console.log(r.lastIndex); // 5 r.lastIndex = 0; // 修改成0,下次从头开始 r.test('abcabc'); //true, 从字符串下标0开始匹配 console.log(r.lastIndex); // 0,下次🈶️从头开始匹配了
Sting对象的一些方法都接受正则对象的参数:
详细的见参考,这里罗列了一些笔记,首先是一张正则知识简图:
量词
正则除了能够匹配字符外还能够匹配位置,图中箭头指向的地方:
图片引用《JavaScript正则迷你书》
位置也是有特性的,而且一个位置能够有多个特性,如字符串abc123
, 正则表达式/^/
,/\b/
, /(?=a)/
都匹配最左侧的位置。除了常见的位置匹配字符^,$,\b,\B外,前瞻和后瞻也是位置匹配:
模式 | 名称 | 描述 |
---|---|---|
(?=exp) | 正向前瞻 | 匹配exp前面的位置 |
(?!exp) | 负向前瞻 | 匹配不知足exp前面的位置,即匹配后面不知足expd的位置 |
(?<=exp) | 正向后瞻 | 匹配exp后面的位置(ES6支持) |
(?<!exp) | 负向后瞻 | 匹配不知足exp后面的位置,即匹配前面不是exp的位置(ES6支持) |
'abc123'.replace(/(?=1)/g, '#'); // abc#123, 匹配字符1前面的位置 'abc123'.replace(/(?!1)/g, '#'); // #a#b#c1#2#3#, 匹配不是字符1前面的位置,有多个位置符合要求 'abc123'.replace(/(?<=1)/g, '#'); // abc1#23, 匹配字符1后面的位置 'abc123'.replace(/(?<!1)/g, '#'); // #a#b#c#12#3#, 匹配不是字符1后面的位置
能够对同一个位置同时进行多个匹配模式,至关于该位置要知足全部的匹配模式。
/^^hello\b(?!\w)/.test("hello "); // true
位置匹配^
重复匹配一个位置,至关于一个位置匹配;
位置匹配\b
和(?!\w)
都是对同一个位置进行匹配,字符b
后面的位置便是个单词结尾又是非单词字符(本例是空格字符)的前面
密码规则校验问题
密码字符集通常是有安全要求的,好比:必须包含数字,大小写字母等。可使用【位置匹配】:
// 规则1 = 长度6到15位,必须是数字,字母,下划线,感叹号,中划线 /^[0-9a-zA-Z_!-]{6,15}$/.test('abc123'); // true,很容易实现 // 规则2 = 规则1 + 必须包含大写字母 /(?=.*[A-Z])^[0-9a-zA-Z_!-]{6,15}$/.test('abc123'); // false /(?=.*[A-Z])^[0-9a-zA-Z_!-]{6,15}$/.test('abC123'); // true // 规则3 = 规则2 + 必须包含下划线 /(?=.*_)(?=.*[A-Z])^[0-9a-zA-Z_!-]{6,15}$/.test('abC123'); // false /(?=.*_)(?=.*[A-Z])^[0-9a-zA-Z_!-]{6,15}$/.test('abC123_'); // true
原理就是经过找知足条件的位置来判断目标字符串是否符合指定的规则。规则2(规则3同理)的正则表达式至关于对起始位置添加了多个匹配条件。
为了判断是否匹配完成,进行了一些尝试。尝试的反作用就是形成回溯(形成匹配位置倒退的行为)。
回溯会影响性能,写正则尽可能规避形成回溯。
function reverse(str) { return str.split('').reverse().join(''); } function format(num) { return reverse(reverse(num + '').replace(/(\d{3})(?!$)/g, '$1,')); } format(123); // '123' format(1234); // '1,234' format(12345); // '12,345' format(123456); // '123,456'
function format(num) { return (num + '').replace(/(?!^)(?=(\d{3})+$)/g, ',') }
一个正则搞定!不过也不能否认,复杂的正则让人难以理解!!!
// 正则表达式使用了i flag function validate(str) { return /^[a-z0-9]{6,18}$/i.test(str); }
function validate(str) { return return /(.)\1{2,}/i.test(str); }
正则表达式使用了捕获分组和反向引用
function mask(idNo) { return idNo.replace(/^(\d{6})\d{8}(.+)$/, '$1********$2') }
function validate(str) { return /^(.)\1*$/.test(str); }
function formatId(idNo) { return idNo.replace(/(\d{4})(?!$)/g, '$1 '); // 正则相似例1中的*金额格式化* }
好玩的正则应用场景持续补充ing