对正则表达式总是望而生畏,现趁有空,补补这块的知识,记录一下正向预查与反向预查:@H_404_1@
@H_404_1@
1.正向预查
现在,我们假设需要仅匹配 Windows,不匹配后面的版本号,并且要求 Windows 后面的版本号只能是 数字类型,换言之,XP 和 Vista 不能被匹配,@H_404_1@在正则表达式中,可以使用 正向预查 来解决这个问题。本例中,写法是:“Windows(?= [\d.]+\b)”。@H_404_1@它的语法是在 子模式内部 前面加“?=”,表示的意思是:首先,要匹配的文本必须满足此子模式前面的表达式(本例,“Windows ”);其次,此子模式不参与匹配。@H_404_1@
Text:@H_404_1@Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively.@H_404_1@Windows 95 and Windows 98 are the successor.@H_404_1@Then Windows 2000 and Windows Xp appeared.@H_404_1@Windows Vista is the Latest version of the family.@H_404_1@
RegEx:@H_404_1@Windows( ?=[\d.]+\b)@H_404_1@
@H_404_1@
Result:(带下划线的为成功匹配的)@H_404_1@Windows1.03 andWindows2.0 fisrt Released in 1985 and 1987 respectively.@H_404_1@Windows95 andWindows98 are the successor.@H_404_1@ThenWindows2000 and Windows Xp appeared.@H_404_1@Windows Vista is the Latest version of the family.
<?PHP $reg="#Windows(?=[\d.]+\b)#"; $str="Windows1.03andWindows2.0fisrtReleasedin1985and1987respectively. Windows95andWindows98arethesuccessor. ThenWindows2000andWindowsXpappeared. WindowsVistaistheLatestversionofthefamily."; if(preg_match_all($reg,$str,$match)){ //code... var_dump($match); }else{ //code... echo("errorcode"); } 结果: array(1){ [0]=> array(5){ [0]=> string(8)"Windows" [1]=> string(8)"Windows" [2]=> string(8)"Windows" [3]=> string(8)"Windows" [4]=> string(8)"Windows" } }
@H_404_1@
可以将 正向预查 理解成为自定义的边界(\b),这个边界位于表达式末。@H_404_1@反言之,你可以将位于表达式末的 \b 理解成非获取匹配的一个特例:(?=[,.\r\n<>;\-])。注意,这里没有写全边界符号。@H_404_1@aaaax-aaa@H_404_1@
aaaaxaaaa
@H_404_1@
x(?=[,.\r\n<>;\-])
@H_404_1@
Result:
aaaax-aaa@H_404_1@aaaaxaaaa
你也可以这样理解上面的匹配过程:
1. 先进行普通匹配:Windows ([\d.]+\b)
2. 然后从匹配文本中将 子模式 内的文本排除掉。
@H_404_1@
2.反向预查
在上面的例子中,我们知道 正向预查 类似于自定义的 位于文本末 的字符边界。那么自然应该有位于文本首的情况,比如说,我们要匹配下面文本中属于 CNY 的金额:@H_404_1@
Text:@H_404_1@CNY: 128.04@H_404_1@USD: 22.5@H_404_1@USD: 23.5@H_404_1@HKD: 1533.5@H_404_1@CNY: 23.78
RegEx:@H_404_1@CNY: \d+\.\d+@H_404_1@
Result:@H_404_1@CNY: 128.04@H_404_1@
USD: 22.5@H_404_1@
USD: 23.5@H_404_1@
HKD: 1533.5@H_404_1@
CNY: 23.78@H_404_1@
与上面类似,我们现在要求仅匹配金额,而不匹配前面的 “CNY:”@H_404_1@正则表达式中,可以使用 反向预查 来解决这个问题。本例中,写法是:(?<=CNY: )\d+\.\d+@H_404_1@反向预查 的语法是在子模式内部前面加“?<=”,表示的意思是:首先,要匹配的文本必须满足此子模式 后面 的表达式(本例,“\d+.\d+”);其次,此子模式不参与匹配。@H_404_1@
<?PHP $reg="#(?<=CNY:)\d+\.\d+#"; $str="CNY:128.04 USD:22.5 USD:23.5 HKD:1533.5 CNY:23.78"; if(preg_match_all($reg,$match)){ //code... var_dump($match); }else{ //code... echo("errorcode"); } 结果: array(1){ [0]=> array(2){ [0]=> string(6)"128.04" [1]=> string(5)"23.78" } }
@H_404_1@与前面类似:你可以将 反向预查 理解成为自定义的边界(\b),这个边界位于 表达式首。@H_404_1@反言之,你可以将位于 表达式首 的 \b 理解成一个非获取匹配的一个特例:(?<=[,.\r\n<>;\-])。注意,我没有写全所有边界。@H_404_1@Text:@H_404_1@aaa-xaaaa@H_404_1@aaaxaaaaa@H_404_1@RegEx:@H_404_1@(?<=[,.\r\n<>;\-])x@H_404_1@Result:@H_404_1@aaa-xaaaaaaaxaaaaa你也可以这样理解上面的匹配过程:1. 先进行普通匹配:(CNY: )\d+\.\d+2. 然后从匹配文本中将 子模式 内的文本排除掉。