共计 3214 个字符,预计需要花费 9 分钟才能阅读完成。
定义
正则表达式 Regular Expression
,由一般字符、元字符和修饰符组成,形容了一种字符串匹配的模式 pattern
,通常被用来检索、取出、替换那些合乎模式的文本。
符号
一般字符
字符 | 含意 |
---|---|
[abc][A-Z] | 匹配括号中 任意一个字符 |
[^abc] | 匹配非括号中 任意一个字符 |
\d | 匹配数字字符,等价于[0-9] |
\w | 匹配字母、数字、下划线,等价于[A-Za-z0-9_] |
\b | 匹配单词边界 |
\s | 匹配不可见字符,等价于[\f\n\r\t\v] |
\f\n\r\t\v | 匹配换页、换行、回车、制表、垂直制表符 |
能够用
\D
来示意对\d
取反,其余同理。
这里须要留神的是,[^]
取反只对任意一个字符无效,如果要匹配多个字符例如非 ab 且非 ac 的话是不能用 [^ab|ac] 来表述的,只能把每个字符拆开表述 [^a][^b]|[^a][^c]
或者应用否定断言 (?!ab)(?!ac)
。
元字符
元字符是一些有非凡含意的字符,简略点说就是在被匹配时须要在前加一个 \
本义的字符。
字符 | 含意 |
---|---|
. | 匹配非换行符,等价于[^\n\r] |
^ | 匹配表达式的开始地位 |
$ | 匹配表达式的完结地位 |
| | 匹配右边或左边 |
()[]{} |
局部元字符 *+?
亦属于限定符,将在限定符中解说。
限定符
限定符用来指定正则表达式的某个 pattern
被匹配次数。
字符 | 含意 |
---|---|
* | 匹配 0 或屡次,等价于{0,} |
+ | 匹配 1 或屡次,等价于{1,} |
? | 匹配 0 或 1 次,等价于{0,1} |
{n} | 匹配 n 次 |
{n,} | 匹配至多 n 次 |
{n,m} | 匹配至多 n 次至少 m 次 |
限定符都是贪心的,会尽可能多的匹配,
?
如果跟在限定符后属于非贪心模式,将实现尽可能少的匹配。
'1 23'.match(/\d{1,2}/g); // ['1', '23']
'1 23'.match(/\d{1,2}?/g); // ['1', '2', '3']
获取匹配
用圆括号 ()
能够分组捕捉 pattern
,多个被获取的匹配能够用 $1…$9 来失去。
/(\w+)\s(\w+)/.test('Brown Bear');
console.log(RegExp.$1); // Brown
console.log(RegExp.$2); // Bear
反向援用符
反向援用容许在正则表达式外部援用之前分组捕捉的文本,准则是由内向内、由左向右。
字符 | 含意 |
---|---|
\num | num 示意所援用分组的编号 |
// 查看日期格局
/\d{4}([/\-.])\d{2}\1\d{2}/.test('1990/08/02')
// 查看成对标签
/<(\w+)>.*?<\/\1>/.test('<span>bear</span>')
非获取匹配符
当不须要失去这组内容时,能够用非获取匹配符来实现。
字符 | 含意 |
---|---|
(?:pattern) | |
(?=pattern) | 断言,预查匹配 pattern 的 |
(?!pattern) | 否定断言,预查不匹配 pattern 的 |
/Bear(?=082)/.test('Bear082') // true
/Bear(?=082)/.test('Bear0802') // false
/Bear(?!082)/.test('Bear082') // false
/Bear(?!082)/.test('Bear0802') // true
这里须要留神的是,JavaScript
起初并不反对反向断言 (?<=)
和反向否定断言 (?<!)
,尽管后续在 ES2018
中补全了这一个性,但这并不会被 babel
或 polyfill
转换,所以须要审慎应用(集体倡议临时弃用)。
修饰符
修饰符用于指定额定的匹配策略,位于正则表达式之外。
/pattern/flags
修饰符 | 含意 | 实例 |
---|---|---|
i | 疏忽大小写 | ‘Bear’.match(/bear/i) |
g | 全局匹配 | ‘bear bear’.match(/bear/g) |
m | 多行匹配,使边界符 ^ 和 $ 匹配每一行 |
‘bear\nbear’.match(/^bear/gm) |
s(ES2018 新增) |
容许 . 匹配换行符\n\r |
‘bear\nbear’.match(/bear./s) |
s
修饰符呈现之前个别用 /s/S
来代替匹配任何字符,ES
新个性另外还新增了 u
和 y
修饰符,因为应用场景相当之少,这里就不花篇幅介绍了。
属性
source
属性返回以后正则表达式的字符串,该字符串不会蕴含两边的斜杠以及任何的标记字符。
const reg = /bear/g;
reg.source; // bear
大家熟知的 underscore
和 lodash
的 template 办法源码中有这么一段经典代码:
export default _.templateSettings = {evaluate: /<%([\s\S]+?)%>/g,
interpolate: /<%=([\s\S]+?)%>/g,
escape: /<%-([\s\S]+?)%>/g
};
var matcher = RegExp([(settings.escape || noMatch).source,
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
].join('|') + '|$', 'g');
- evaluate 对应表达式 <% console.log(‘Bear’); %>
- interpolate 对应插入值 <%= name %>
- escape 对应本义值 <%- value %>
当须要将这三种正则合并成一种使其都能匹配到时,source
的奇妙用法就能帮忙代码简洁易懂许多。
办法
String.prototype
- replace
- match 返回一个字符串匹配正则表达式的后果,与
exec
相似但不如其弱小 - search 返回搜寻匹配的索引
鉴于 replace
的高频应用次数及弱小性能,这里额定花些篇幅解说下。
参数 | 含意 |
---|---|
regexp | substr | 被替换的正则表达式匹配的文本或字符串,字符串格局时仅第一个匹配项会被替换 |
newSubStr | function | 用于替换的字符串值或生成替换文本的函数 |
用于替换的字符串 newSubStr 中 $
字符具备特定的含意:
字符 | 含意 |
---|---|
$$ | $ |
$& | 匹配的文本 |
$` | 匹配的文本的右边的文本 |
$’ | 匹配的文本的左边的文本 |
$1…$99 | 匹配的第 1 到 99 个被捕捉的文本,如果不存在该分组则间接沿用字面量 |
'Brown Bear'.replace(/(\w+)\s(\w+)/, '$2 $1'); // 'Bear Brown'
'Brown Bear'.replace(/(\w+)\s(\w+)/, '$3 $2 $1'); // '$3 Bear Brown'
RegExp.prototype
- test 查看正则表达式与指定的字符串是否匹配,返回
true
或false
- exec 在一个指定字符串中执行一个搜寻匹配,返回一个后果数组或
null
罕用案例
手机号加密
'13012345678'.replace(/(\d{3})\d{4}/, '$1****');
前端加密属于自欺欺人,还是要辨别场合应用,千万不要因为学到了就装 X(我来做!一行正则搞定的事件!)。
千位分隔符
'12345678'.replace(/(\d{1,3})(?=(\d{3})+$)/g, '$&,');
这里其实还有一种更高大上的实现形式:
(12345678).toLocaleString();
可能有仔细的同学要问,如果分隔符是 .
怎么办呢,这个办法还能用吗?答复是当然,能够通过第一个参数区域 locales 来反对,这里就不赘述了。
验证明码复杂度
// 要求明码中必须蕴含大小写字母、数字,至多 8 个字符至少 16 个字符
/^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])).{8,16}$/.test('Bear0802');
可视化工具
https://tooltt.com/regulex/
- 反对正则可视化
- 反对导出为图片,不便分享、留存
结语
正则表达式须要弱小的基本功作为撑持,了解吃透它并不容易,真正用到它时,先不要忙于生吞活剥,列举出所有场景并联合可视化工具,写出合乎本人需要的正则表达式。