JS基础 - 正则
正则的语法及相关 API
语法
创建
创建一个正则表达式对象有两种方式:
使用
new RegExp("pattern", "flags"),pattern 是模式,flags 是修饰符。例如:
new RegExp('name','g')使用斜杠语法,这种写法的缺点是他不接受变量插入
例如:
/name/g
修饰符
i:不区分字母的大小写g:查找所有匹配项m:多行模式,只会对^和$造成影响举个例子:
let str = `1st place: Winnie 2nd place: Piglet 33rd place: Eeyore`; str.match(/^\d+/g); // output: 1此时并没有输出所有数字,即使 Winnie 后的字符串进行了换行,但依然将其视作一行字符串,将正则改写成
/^\d+/gm就可以正常输出结果u:打开 unicode 支持(在 firefox 和 edge 中使用会有 bug)y:粘滞模式
相关API
regexp.test(str)
用途:判断正则表达式与指定字符串是否匹配。
如果找到匹配项返回true,没有找到则返回false
/\d/.test('123') // output: true
regexp.exec(str)
用途:在字符串中找到匹配的字符。
如果没有找到匹配的字符,则返回null
在调用exec方法时,如果正则为全局匹配时,其返回的结果跟match方法非全局匹配下的结果一致,不过exec会维护一个lastIndex属性,当匹配到字符串时,会将lastIndex属性设置为当前匹配项的结束的位置:
let reg = /\d/g;
reg.exec('123');
// output:
// 0: "1"
// groups: undefined
// index: 0
// input: "123"
console.log(reg.lastIndex); // output: 1 
// 再次执行
reg.exec('123');
// output:
// 0: "2"
// groups: undefined
// index: 1
// input: "123"
console.log(reg.lastIndex); // output: 2
如果正则不是全局匹配,则会每一次都将 lastIndex 重置为 0 ,并重头开始查找:
let reg = /\d/;
reg.exec('123');
console.log(reg.lastIndex); // output: 1 
// 再次执行
reg.exec('123');
console.log(reg.lastIndex); // output: 1
如果在不使用全局匹配的情况向下,依然要记住上一次的 lastIndex,可以使用y修饰符:
let reg = /\d/y;
reg.exec('123');
console.log(reg.lastIndex); // output: 1 
// 再次执行
reg.exec('123');
console.log(reg.lastIndex); // output: 2
str.search(regexp)
用途:搜索一个匹配字符,返回首次匹配到的索引,如果没有找到匹配字符,则返回-1
/\d/.test('123') // output: 0
str.match(regexp)
用途:在字符串中找到匹配的字符。
如果没有找到匹配的字符,则返回null
如果正则还有全局搜索标记g,则会返回匹配倒的字符的数组:
let str = "name=nick; first_name=john"
str.match(/name=([^;]{0,})/g) 
// output: ["name=nick", "name=john"]
如果不含标记g,则会返回第一个匹配项,包含其详细信息,第一项是完全匹配的内容,后几项是与捕获括号相对应的匹配字符串
let str = "name=nick; first_name=john"
str.match(/name=([^;]{0,})/) 
// output: 
// 0: "name=nick"
// 1: "nick"
// groups: undefined
// index: 0
// input: "name=nick; first_name=john"
如果使用 index 来获取匹配项不方便,可以对捕获括号进行进行命名,在捕获括号后跟上?<name>即可对组进行命名(要注意的是IE11不支持组命名):
let str = "name=nick; first_name=john"
str.match(/name=(?<name>[^;]{0,})/)
// output:
// 0: "name=nick"
// 1: "nick"
// groups: {name: "nick"}
// index: 0
// input: "name=nick; first_name=john"
str.replace(regexp, replacement)
用途:在字符串中找到匹配的字符并使用新字符进行替换(生成新字符串,不会修改原字符串)。
有两种方式可以实现替换
一种方式是使用$n的方式对捕获组内的字符串进行替换:
let str = "nick john";
str.replace(/(\w+) (\w+)/, '$2, $1'); // output: john,nick
另一种方式是通过组名来替换,引用方式为$<name>:
let str = "nick john";
str.replace(/(?<first>\w+) (?<second>\w+)/, '$<second>, $<first>'); // output: john,nick
正则符号
| 字符 | 含义 | 
|---|---|
| \ | 转译字符 常用转译: \d:匹配一个数字,等价于[0-9]\D:匹配一个非数字,等价于[^0-9]\n:匹配一个换行符\r:匹配一个回车符\s:匹配一个空白字符\S:\s取反\w:匹配一个单字字符(字母数字或者下划线,等价于[A-Za-z0-9_])\W:\w取反 | 
| ^ | 匹配输入的开始,当^出现在一个字符合集内时表示取反 | 
| $ | 匹配输入的结尾 | 
| | | 或 | 
| * | 匹配前一个表达式的0次或多次,等价于{0,} | 
| + | 匹配前一个表达式的1次或多次,等价于{1,} | 
| ? | 匹配前一个表达式的0次或1次,等价于{0,1},正则默认是贪婪模式,即尽可能多的匹配,加上问号后就变成了非贪婪模式 | 
| . | 匹配换行符以外的所有单个字符 | 
| (x) | 捕获括号,记住匹配项,它表示一个区块,例如/foo{1,2}/中{1,2}匹配的是字母o,而/(?:foo){1,2}/匹配的是整个单词foo | 
| (?:x) | 非捕获括号,不记住匹配项,匹配项不会出现在 match 方法的结果数组中 | 
| x(?=y) | 先行断言,foo(?=abc)表示当 foo 后面跟着 abc 时才会才会匹配 foo | 
| (?<=y)x | 后行断言,(?<=abc)foo表示当 foo 的前面是 abc 时才会匹配 foo注意:IE 和 safari 并不支持(兼容性)  | 
| x(?!y) | 正向否定查找,foo(?!abc)仅当 x 后面不跟着 abc 时才会匹配 foo | 
| (?!y)x | 反向否定查找,(?!abc)foo仅当 x 前面不跟着 abc 时才会匹配 foo | 
| {} | 匹配次数,{n}表示前面单个字符出现了 n 次,{n,}表示前面单个字符至少出现了 n 次,{n,m}表示前面单个字符出现次数大于等于 n,小于等于 m | 
| [] | 字符合集,匹配方括号中的单个任意字符,其内的特殊字符不需要转义 若用 -分割,则表示一个范围,/[abcd]/和/[a-d]/是一样的例如: /V[oi]la/能够匹配Vola或者Vila,单不能匹配Voila | 
| [^] | 反向字符集,[^a-d]表示匹配不含 a 到 d 的字母的字符 | 
| \b | 边界,类似于^和$,当遇到\b时会检查字符串位置是否处于边界/\bJava\b/表示匹配 Java 字符串,且两遍的字符不属于\w,Hello,Java能够匹配,但Hello,Javascript无法匹配\B表示非边界值 | 
常用正则
手机号正则
/^1[3-9]\d{9}$/
身份证正则
/(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}$)/