正则要单独开一章
善用new RegExp
用它有两个好处,一是避免重复初始化regxp;二是可以以string的形式来写,斜杠等不用加反义。
匹配与groups
查询并替换 {{xxx}}
原:
const reg = /\{\{(.+)\}\}/
return str.replace(reg, (m, $1) => console.log(m, $1))
// {{aaa}} => {{aaa}} aaa
// {{aaa}}hhh{{bbb}} => {{aaa}}hhh{{bbb}} aaa}}hhh{{bbb (×)
正确:
const reg =/\{\{((?:.|\n)+?)\}\}/g
// 其实最关键的是加?啦 把贪婪模式替换为懒惰模式
默认match的内容是整个匹配项,如果只需要部分内容的话,用group。
'111{{aaa}}222'.match(/{{(.+?)}}/)
// => \["{{aaa}}", "aaa", index: 3, input: "111{{aaa}}222", groups: undefined\]
不过此时的groups还是undefined。要显示group的内容(named captured groups),可以以?<groupName>
的方式显性命名(超好用):
'111{{aaa}}222'.match(/{{(?<mustache>.+?)}}/)
// => \["{{aaa}}", "aaa", index: 3, input: "111{{aaa}}222", groups: {mustache: "aaa"}\]
不过,全局match有个小坑:
'111{{aaa}}222'.match(/{{(.+?)}}/g)
// => \["{{aaa}}"\]
可以看到此时没有单个match中额外的内容了。不过stage-4里有个新apistring.prototype.matchAll
,会返回一个iterator
(为什么是iterator而不就是一个数组呢,因为js期望遍历操作由用户来控制,避免无效遍历),执行后得到的值和match
单个时一模一样:
\[...'111{{aaa}}222'.matchAll(/{{(.+?)}}/g)\]
// => \[\["{{aaa}}", "aaa", index: 3, input: "111{{aaa}}222", groups: {mustache: "aaa"}\]\]
如果在实际情况中使用,需要引入babel-polyfill或者es-shim。
换行相关
- 如何 match line breaks?
Linux和新Mac use
\n
for a new-line; Windows\r\n
and old Macs\r
. 所以可以用(\r\n|\r|\n)
- (.+) Couldn't match 含有 line break 的 text
使用
[^.]+
转译
在处理用户输入的字符串时,一定要先转译。用MDN上的这一串简单替换就好了~
function escapeRegExp(string) {
return string.replace(/\[.\*+?^${}()|\[\\\]\\\\\]/g, "\\\\$&");
//$&表示整个被匹配的字符串
}