从常见案例探索JS正则表达式用法
如何写一个正则表达式
拆成(取值范围+量词)这样的组合,例如qq号码验证:号码数字5-15位,并且不以0开头
- 拆分(1位:1-9的数字)(4-14位:0-9的数字)
- 初步获得
pattern = /[1-9][0-9]{4,14}/
- 上述模式是正确的吗?我们可以做个测试看样子pattern是错误的,它可以匹配超过15位的号码。即只要字符串中有符合该pattern的子串,就会匹配。(比如a123456b就会匹配)
1
2let pattern = /[1-9][0-9]{4,14}/
console.log(pattern.test('555555555555555555')) // 18位 - 修改 => 加入元字符
^
和$
表示字符串的开始和结束 =>pattern = /^[1-9][0-9]{4,14}$/
常见使用方法以及案例
1. 移除className - 元字符\b
使用元字符\b
(\b
匹配单词的开始或结束)匹配要移除的className
1 | <script type="text/javascript"> |
2. 找句子中hi后面不远处跟着一个Lucy那一段 - 元字符\b
.
匹配除换行符以外的任意字符,*
表示重复零次或多次,那么.*
表示单词hi和单词Lucy中间有0个或多个字符
1 | \bhi\b.*\bLucy\b |
3. 把一串数字表示成千位分隔形式 - 正向预查a(?=b)
- 从后往前匹配三个数字
pattern = /(\B\d{3})+$/g
- 利用正向预查匹配前面的空格
pattern = /(?=(\B\d{3})+$)/g
可以利用replace的第二个参数查看具体匹配详情1
2
3let num = 100000000
// \B匹配不是单词开头或结束的位置
console.log(num.toString().replace(/(?=(\B\d{3})+$)/g, ','))把一串数字表示成千位分隔形式1
2
3
4
5
6
7
8let num = 100000000
// \B匹配不是单词开头或结束的位置
console.log(num.toString().replace(/(?=(\B\d{3})+$)/g, function (...params) {
console.log(params)
return ','
}
))
// 可以看到输出两次
4. 国内电话号码验证 - 分支条件|
- 验证国内电话号码,例如0555-6581752、021-86128488
拆分:- 0开头
- 后接
3个数字+‘-’+7个数字(非0开头)
或者2个数字+‘-’ +8个数字(非0开头)
使用\d代表[0-9]1
pattern = /(^0[0-9]{3}-[1-9][0-9]{6}$)|(^0[0-9]{2}-[1-9][0-9]{7}$)/
1
pattern = /(^0\d{3}-[1-9]\d{6}$)|(^0\d{2}-[1-9]\d{7}$)/
5. 分组与捕获
1
2
3
4
5
6
7// 匹配abab
console.log(/(ab){2}/.test('ababcc')) // 此处将ab重复两次
// 匹配所有js与css文件
// 限定分支
console.log(/.*\.(js|css)$/.test('hello.js'))
// 获取js或css文件名
console.log('hello.js'.replace(/(.*)\.(js|css)$/, '$1'))6. 获取链接https://www.baidu.com?name=astar&age=200中name的值
- [^x]匹配除了x以外的任意字符
- [^aeiou]匹配除了aeiou这几个字母以外的任意字符,
<a[^>]+>
匹配用尖括号括起来的以a开头的字符串,例如<as>
- ()代表分组ps: decodeURIComponent() 函数可对 encodeURIComponent() 函数编码的 URI 进行解码。
1
2
3
4
5
6
7function getParam(attr) {
// window.location.search => ?name=astar&age=100
let pattern = new RegExp(`[?&]${attr}=([^&]*)`)
let match = pattern.exec(window.location.search)
return match && decodeURIComponent(match[1])
}
console.log(getParam('name'))
7. 获取url中的所有参数
1 | function getParams (url) { |
8. 正则从2018-10-07T11:48:47 Asia/zh-cn 提取出来结果[2018,10,07,11,48,47]
1 | str.match(/\d{1,}/g) |
9. 反向引用
\number
或 \k
,使用方法不同,效果一致。
\b(\w+)\b\s+\1\b
可以用来匹配重复的单词,像go go, 或者kitty kitty(\1表示分组1匹配的文本)\b(?<Word>\w+)\b\s+\k<Word>\b
自定义分组名为Word
10. 变量名转为驼峰法
1 | function toCamel (s) { |
11. 其他练习题集锦
各类符号及其含义
元字符
字符 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 [a-zA-Z0-9_] |
\s | 匹配任意的空白符 [\r\n\t\f] |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
反义
字符 | 说明 |
---|---|
\W | 匹配任意不是字母,数字,下划线,汉字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非数字的字符 |
\B | 匹配不是单词开头或结束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou这几个字母以外的任意字符 |
重复限定符
字符 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
标志符号
字符 | 说明 |
---|---|
g | 全局模式 |
i | 不区分大小写 |
m | 多行模式 |
常见分组语法
分类 | 代码/语法 | 说明 |
---|---|---|
捕获 | (exp) | 匹配exp,并捕获文本到自动命名的组里 |
捕获 | (? | 匹配exp,并捕获文本到名称为name的组里,也可以写成(?’name’exp) |
捕获 | (?:exp) | 匹配exp,不捕获匹配的文本,也不给此分组分配组号 |
零宽断言 | (?=exp) | 匹配exp前面的位置 |
零宽断言 | (?<=exp) | 匹配exp后面的位置 |
零宽断言 | (?!exp) | 匹配后面跟的不是exp的位置 |
零宽断言 | (?<!exp) | 匹配前面不是exp的位置 |
注释 | (?#comment) | 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读 |
懒惰限定符
代码/语法 | 说明 |
---|---|
*? | 重复任意次,但尽可能少重复 |
+? | 重复1次或更多次,但尽可能少重复 |
?? | 重复0次或1次,但尽可能少重复 |
{n,m}? | 重复n到m次,但尽可能少重复 |
{n,}? | 重复n次以上,但尽可能少重复 |
RegExp实例方法
exec()
该方法是专门为捕获组设计的。
接收字符串参数,返回包含第一个匹配项信息的数组;或者在没有匹配项的情况下返回null。返回的数组虽然是Array的实例,但包含两个额外的属性:index和input。其中,index表示匹配项在字符串中的位置,而input表示应用正则表达式的字符串。
即使正则表达式设置了全局,每次也只会返回一个匹配项,需要多次调用exec()方法。
1 | var text = 'mom and dad and baby' |
test()
返回true或false
接收字符串参数,在模式与该参数匹配的情况下返回true,否则返回false。
test方法经常出现在验证用户输入的情况下,因为我们只想知道输入是不是有效,至于他为什么无效就无关紧要了。
1 | var text = '000-00-0000' |
字符串的方法
match()
返回匹配的内容组成的数组,失败返回null
search()
返回第一个匹配成功的字符串片段开始的位置,失败则返回-1
replace()
替换与正则表达式匹配的子串,并返回替换后的字符串,若不设置全局g,只会替换第一个匹配成功的字符串片段。
split()
把一个字符串分割成数组
【参考】