为止,这种往回释放字符的行为在正则术语中称为"回溯"。而固化分组后,.*
已匹配后面所有内容,这些内容一经匹配绝不交回,即无法回溯。
但是,如果正则表达式是hel(?>.* world)
,即将原来分组外面的内容放进了分组内部,这时在分组内部是会回溯的,也就是说能匹配"hello world"。
固化分组看上去挺简单的,此处也仅介绍了它最简单的形式。但实际上固化分组很复杂,它涉及了非常复杂的正则引擎匹配原理和回溯机制。如果有兴趣,可以阅读《精通正则表达式》一书的第四章。
"环视"锚定,即lookaround anchor,也称为"零宽断言",它表示匹配的是位置,不是字符。
关于"环视"锚定,最需要注意的一点是匹配的结果不占用任何字符,它仅仅只是锚定位置。
例如"your name is longshuai MA"和"your name is longfei MA"。使用(?=longshuai)
将能锚定第一个句子中单词"longshuai"前面的空字符,但它的匹配结果是"longshuai"前的空白字符,所以(?=longshuai)long
才能代表"long"这几个字符串,所以仅对于此处的两个句子,long(?=shuai)
和(?=longshuai)long
是等价的。
一般为了方便理解,在顺序环视的时候会将匹配内容放在锚定括号的左边(如long(?=longshuai)
),在逆序环视的时候会将匹配的内容放在锚定括号的右边(如(?<=long)shuai
)。
另外,无论是哪种锚定,都是从左向右匹配再做回溯的(假设允许回溯),即使是逆序环视。
例如:
逆序环视的表达式必须只能表示固定长度的字符串。例如(?<=word)
或(?<=word|word)
可以,但(?<=word?)
不可以,因为?
匹配0或1长度,长度不定,它无法对左边是word还是wordx做正确判断。
在PCRE中,这种变长的逆序环视锚定可重写为(?<=word|words)
,但perl中不允许,因为perl严格要求长度必须固定。
perl中的\Q...\E
用来强制包围一段字符,使得里面的正则符号都当做普通字符,不会有特殊意义,它是一种非常强的引用。但注意,它无法强制变量的替换。
例如:
因为可以在正则模式中使用变量替换,所以我们可以将正则中的一部分表达式事先保存在变量中。例如:
但是,这样缺陷很大,在保存正则表达式的变量中存放的特殊字符要防止有特殊意义。例如,当使用m//
的方式做匹配分隔符时,不能在变量中保存/
,除非转义。
perl提供了qr/pattern/
的功能,它把pattern部分构建成一个正则表达式对象,然后就可以在正则表达式中直接引用这个对象,更方便的是可以将这个对象保存到变量中,通过引用变量的方式来引用这个已保存好的正则对象。
还允许为这个正则对象设置修饰符,比如忽略大小写的匹配修饰符为i,这样在真正匹配的时候,就只有这一部分正则对象会忽略大小写,其余部分仍然区分大小写。