java正则断⾔_Java正则表达断⾔篇
正则表达式的先⾏断⾔和后⾏断⾔⼀共有4种形式:
(?=pattern) 零宽正向先⾏断⾔(zero-width positive lookahead assertion)
(?!pattern) 零宽负向先⾏断⾔(zero-width negative lookahead assertion)
(?<=pattern) 零宽正向后⾏断⾔(zero-width positive lookbehind assertion)
(?
这⾥⾯的pattern是⼀个正则表达式。
如同^代表开头,$代表结尾,\b代表单词边界⼀样,先⾏断⾔和后⾏断⾔也有类似的作⽤,它们只匹配某些位置,在匹配过程中,不占⽤字符,所以被称为“零宽”。所谓位置,是指字符串中(每⾏)第⼀个字符的左边、最后⼀个字符的右边以及相邻字符的中间(假设⽂字⽅向是头左尾右)。
下⾯分别举例来说明这4种断⾔的含义。
(?=pattern) 正向先⾏断⾔
代表字符串中的⼀个位置,紧接该位置之后的字符序列能够匹配pattern。
例如对”a regular expression”这个字符串,要想匹配regular中的re,但不能匹配expression中的re,可以⽤”re(?=gular)”,该表达式限定了re右边的位置,这个位置之后是gular,但并不消耗gular这些字符,将表达式改为”re(?=gular).”,将会匹配reg,元字符.匹配了g,括号这⼀砣匹配了e和g之间的位置。
(?!pattern) 负向先⾏断⾔
代表字符串中的⼀个位置,紧接该位置之后的字符序列不能匹配pattern。
例如对”regex represents regular expression”这个字符串,要想匹配除regex和regular之外的re,可以⽤”re(?!g)”,该表达式限定了re右边的位置,这个位置后⾯不是字符g。负向和正向的区别,就在于该位置之后的字符能否匹配括号中的表达式。
(?<=pattern) 正向后⾏断⾔
代表字符串中的⼀个位置,紧接该位置之前的字符序列能够匹配pattern。
例如对”regex represents regular
expression”这个字符串,有4个单词,要想匹配单词内部的re,但不匹配单词开头的re,可以⽤”(?<=\w)re”,单词内部的re,在re前⾯应该是⼀个单词字符。之所以叫后⾏断⾔,是因为正则表达式引擎在匹配字符串和表达式时,是从前向后逐个扫描字符串中的字符,并判断是否与表达式符合,当在表达式中遇到该断⾔时,正则表达式引擎需要往字符串前端检测已扫描过的字符,相对于扫描⽅向是向后的。
(?
代表字符串中的⼀个位置,紧接该位置之前的字符序列不能匹配pattern。
例如对”regex represents regular
expression”这个字符串,要想匹配单词开头的re,可以⽤”(?
对于这4个断⾔的理解,可以从两个⽅⾯⼊⼿:
1.关于先⾏(lookahead)和后⾏(lookbehind):正则表达式引擎在执⾏字符串和表达式匹配时,会从头到尾(从前到后)连续扫描字符串中的字符,设想有⼀个扫描指针指向字符边界处并随匹配过程移动。先⾏断⾔,是当扫描指针位于某处时,引擎会尝试匹配指针还未扫过的字符,先于指针到达该字符,故称为先⾏。后⾏断⾔,引擎会尝试匹配指针已扫过的字符,后于指针到达该字符,故称为后⾏。
2.关于正向(positive)和负向(negative):正向就表⽰匹配括号中的表达式,负向表⽰不匹配。
对这4个断⾔形式的记忆:
1.先⾏和后⾏:后⾏断⾔(?<=pattern)、(?
2.正向和负向:不等于(!=)、逻辑⾮(!)都是⽤!号来表⽰,所以有!号的形式表⽰不匹配、负向;将!号换成=号,就表⽰匹配、正向。
我们经常⽤正则表达式来检测⼀个字符串中包含某个⼦串,要表⽰⼀个字符串中不包含某个字符或某些字符也很容易,⽤[^...]形式就可以了。要表⽰⼀个字符串中不包含某个⼦串(由字符序列构成)呢?
⽤[^...]这种形式就不⾏了,这时就要⽤到(负向)先⾏断⾔或后⾏断⾔、或同时使⽤。时间正则表达式java
例如判断⼀句话中包含this,但不包含that。
包含this⽐较好办,⼀句话中不包含that,可以认为这句话中每个字符的前⾯都不是that或每个字符的后⾯都不是that。正则表达式如下:
^((?
对于”this is the case”这句话,两个表达式都能够匹配成功,⽽”note that this is the case”都匹配失败。
在⼀般情况下,这两个表达式基本上都能够满⾜要求了。考虑极端情况,如⼀句话以that开头、以that结尾、that和this连在⼀起时,上述表达式就可能不胜任了。
如”note thatthis is the case”或者”this is the case, not that”等。
只要灵活运⽤这⼏个断⾔,就很容易解决:
^(.(?
^(.(?
^((?!that).)*this(.(?
^((?!that).)*this((?!that).)*$
这4个正则表达式测试上述的⼏句话,结果都能够满⾜要求。
上述4种断⾔,括号⾥的pattern本⾝是⼀个正则表达式。但对2种后⾏断⾔有所限制,在Perl和Python
中,这个表达式必须是定长(fixed
length)的,即不能使⽤*、+、?等元字符,如(?<=abc)没有问题,但(?<=a*bc)是不被⽀持的,特别是当表达式中含有|连接的分⽀时,各个分⽀的长度必须相同。之所以不⽀持变长表达式,是因为当引擎检查后⾏断⾔时,⽆法确定要回溯多少步。Java⽀持?、{m}、{n,m}等符号,但同样不⽀持*、+字符。JavaScript⼲脆不⽀持后⾏断⾔,不过⼀般来说,这不是太⼤的问题
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论