以前大三学习《编译原理》的时候老师讲了点叫断言的东西,可是这门课压根就没听懂过,因此一直找不到有价值的东西,好吧原谅我懒惰无知,理论不适合我,我只适合搬砖。许久以后一些关于正则的黑科技才发现正则里也有较断言的东东,好吧得了解了解这是什么。javascript
引用一段来自百科的说明java
用于查找在某些内容(但并不包括这些内容)以前或以后的东西,也就是说它们像b,^,$那样用于指定一个位置,这个位置应该知足必定的条件(即断言),所以它们也被称为零宽断言。(来自百度百科)正则表达式
断言在一些教材里也称做环视
。c#
前瞻断言浏览器
(?=exp)
顺序确定环视,表示所在位置右侧可以匹配exp网络
(?!exp)
顺序否认环视,表示所在位置右侧不能匹配exp学习
后瞻断言测试
(?<=exp)
逆序确定环视,表示所在位置左侧可以匹配expcode
(?<!exp)
逆序否认环视,表示所在位置左侧不能匹配expip
解析:
前瞻断言(从当前位置向前测试)和后瞻断言(从当前位置向后测试)。
具体的例子看使用方法吧。
注:
括号是必须的,写法:(?!=...)
有些语言并不彻底支持,好比:javascript的正则并不支持后瞻断言
表达式,使用了会报错的。
其中exp
是一个正则表达式能够是子模式,如:(?=((exp))
。
环视也称断言;断言是不占用字符串的((?=exp)因此不能引用,exp是占用字符串的)
(?=exp)
顺序确定环视,表示所在位置右侧可以匹配exp
来个javascript的例子,匹配.gif
的文件名
var s="img.jpg,abc.gif,123.jpeg"; s.match(/\w*(?=\.gif)/);
结果:
["abc"]
/\w*(?=\.gif)/
中的\w*
表示能够有零个或多个字符,匹配到的是abc
,那么(?=.gif)这个匹配到什么?其实他匹配到的只是一个位置,这就是断言的初衷,匹配到的是介于abc
与.gif
的位置。
好吧不信来验证下:
去掉正则表达式的\w*
,在匹配到的内容替换成#
var s="img.jpg,abc.gif,123.jpeg"; s.replace(/(?=\.gif)/,"#");
结果:
"img.jpg,abc#.gif,123.jpeg"
回到定义:(?=exp)
顺序确定环视,表示所在位置右侧可以匹配exp;那么/\w*(?=\.gif)/
的意思就是以.gif
做为右边的位置才匹配成功,那就会匹配到abc.gif
这里就成功了,以前说过断言匹配不占用字符宽度(即不结果不会包含断言部分),因此匹配到的字符串就是\w*
即'abc'。
(?!exp)
顺序否认环视,表示所在位置右侧不能匹配exp
例子:匹配非.gif
的文件名
var s="img.jpg,abc.gif,123.jpeg"; s.match(/(\w*)(?:\.)(?!gif)\w*/g);
结果:
["img.jpg", "123.jpeg"]
/(\w*)(?:\.)(?!gif)\w*/g
这个正则表示(\w*)(?:\.)
的右边不是gif匹配成功。
对于后瞻断言
的例子这里不举例子,若是哪位有空填下吧。
来看一个来自网络的问答例子:把一串数
10000000000
字以,
分隔成10,000,000,000
这个例子0
有点多看着耀眼,先从简单的开始;好吧咱们换一串字符串好比:12345678
转换成12,345,678
。
正则怎么实现呢?
看代码:
var s="12345678"; s.replace(/(?=(\d{3})+(?!\d))/g,",");
是的就这样就能够了。
好吧,来分析下原理:
/(?=(\d{3})+(?!\d))/g
,其中(\d{3})+
表示前面的三个数字串至少出现一组,然后接(?!\d)
则表示的是数字的右边不是数字,
那么就是结尾,那/(?=(\d{3})+(?!\d))/
匹配到的位置就是12
与345678
之间的位置,加了g
表全局匹配,
因此继续匹配到知足条件的345
与678
之间的位置,在这些加,
就有了12,345,678
了。
若是想看这个例子的过程能够改写下代码:
var s="12345678"; s.replace(/(?=((\d{3})+)(?!\d))/g,function(){console.log(arguments);return ","});
结果:
循环1:["", "345678", "678", 2, "12345678"]
循环2:["", "678", "678", 5, "12345678"]
返回值:"12,345,678"
好吧,原理再也不细说,本身复制代码到浏览器控制台执行看效果。
那么这个10000000000
转成10,000,000,000
就很简单了。
可是若是数字串的位数是3的倍数会出如今数字串前面也有一个,
号,好吧再正则去掉result.replace(",","")
。
上面举的一些例子可能不足以说明问题,若是你是精通正则的高手望勿喷,固然多多指教那就更好了。