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}$)/