场景
要将下面的字符串截取两个{title:***,url:***}
来。
1
2
3
4
5
|
<script>
{title:
'RegExp 对象参考手册',url:
'http://sodino.com/regexp.asp'},
{title:
'w3cSchool script', url:
'http://www.w3cSchool.com'},
{}
</script>
|
正则表达式一
1
2
3
4
5
6
7
8
9
10
|
var
string
=
'<script>'
+
"{title:'RegExp 对象参考手册',url:'http://sodino.com/regexp.asp'},"
+
"{title:'w3cSchool script', url:'http://www.w3cSchool.com'},"
+
"{}"
+
'</script>';
var reg
=
/
\{
.
+\}/g;
var result
=
string
.
match(reg);
console
.
log(result);
|
这个毫无疑问是全匹配,即输出为第一个{
到最后一个}
之间的全部内容:
1
2
|
D:
\github
\niVoVin>node test.js
[ '
{title:
\'RegExp 对象参考手册
\',url:
\'http://sodino.com/regexp.asp
\'
},
{title:
\'w3cSchool script
\', url:
\'http://www.w3cSchool.com
\'
},
{
}'
]
|
正则表达式二
书上说在表达式的后面加上?
就是非贪婪模式了。即n?
匹配包含零个或一个n
的字符串。
那么目前想的是只匹配一个}
,那么将表达式修改为如下:
运行一下代码,发现输出是竟然是第一个{
到字符串结尾:
1
2
|
D:
\github
\niVoVin>node test.js
[ '
{title:
\'RegExp 对象参考手册
\',url:
\'http://sodino.com/regexp.asp
\'
},
{title:
\'w3cSchool script
\', url:
\'http://www.w3cSchool.com
\'
},
{
}</script>'
]
|
那?
的作用竟然是忽略}
吗?
陷入了深深的疑惑……
排查问题
当表达式一和表达式二对比时,直觉告诉你是由于引入?
才导致的错误。
那么需要来验证下。
更换表达式,验证是否?
一样会忽略掉>
???
执行输出得到:
1
2
|
D:\github\niVoV
in>node test.js
[
'script>',
'script',
'script>' ]
|
所以?
并不是忽略的作用。所以直觉不对。
再看表达式二的输出结果,结果是将第一个{
后的内容全部输出,那就是说表达式二的结果是由于一直在匹配.+
(任意数量的任意字符,除了换行和结束符),而没有匹配到截止符}?
的原因。
而由于}?
处于可匹配可不匹配的情况,解释器优先选择不匹配,导致截止符}
是无效的。
参考链接正则基础之——贪婪与非贪婪模式
那么解决办法就变为截止符}
不可设置为非贪婪,这样才有截止作用,而对应的是对.+
(任意字符)执行非贪婪匹配,尽可能少的匹配{
与}
之间的内容。
正则表达式三
输出结果:
1
2
3
|
D:
\github
\niVoVin>node test.js
[ '
{title:
\'RegExp 对象参考手册
\',url:
\'http://sodino.com/regexp.asp
\'
}',
'
{title:
\'w3cSchool script
\', url:
\'http://www.w3cSchool.com
\'
}'
]
|
很圆满。
由于.+
中+
表示最少出现一次.
,所以第三行的空{}
并没有被匹配成功。
结论
在表达式三中,.+
表达任意字符串,}
是截止符。
当使用n+
n*
n?
截取任意字符串时,如果待截取内容包括任意字符串,则非贪婪模式应尽可能少的匹配任中间的任意字符串,而非尽可能少的匹配截止符。
About Sodino