The qr/…/Operator and Regex Objects
在第2章和第6章已经简要介绍过(☞76,277)一元运算符qr/…/,其运算元为正则表达式,返回regex对象。返回的对象可以被之后的正则运算符用来匹配、替换、分割,或者可以作为其他的更长表达式的一部分。
regex对象主要用来把正则表达式封装为一个单元,构建大的正则表达式,以及提高效率(在正则表达式编译时提高控制能力,讨论见下文)。
291页已经介绍过,用户可以使用自己的分隔符,例如qr{…}或者qr!…!。它还支持核心修饰符/i、/x、/s、/m和/o。
构建和使用regex对象
Building and Using Regex Objects
下面的表达式来自第2章(☞76):
第一行代码把匹配主机名所用的简单正则表达式封装为regex对象,保存到变量$Hostname-Regex中。下一行使用该变量构建匹配HTTP URL的regex对象,保存到$HttpUrl中。构建完成之后就可以以多种方式使用,例如:
用来检测,或者:
用来搜索和显示所有的HTPP URL。
如果按照第5章的讲解(☞205)修改$HostnameRegex:
它的使用方式与之前的例子相同(开头没有「^」,结尾没有「$」,也没有捕获型括号),所以,我们的替换不受限制。这样能得到更准确的$HttpUrl。
匹配模式(即使不设置)是不可更改的
qr/…/支持292页介绍的核心修饰符。regex对象一旦构建完成,对应的匹配模式就不能更改了,即使regex对象所在的m/…/有自己的修饰符也是如此。下面的代码就不正确:
这里希望用/x修饰$WordRegex的匹配模式,但是这并不管用,因为在$WordRegex生成时修饰符(即使不设置)被锁定在qr/…/中。所以,修饰符必须在恰当的时候使用。
下面的代码则没有问题:
现在来比较开始的代码和下面的代码:
这段代码没问题,尽管$WordRegex生成时没有任何修饰符。因为$WordRegex是普通变量,保存普通的字符串,用作 m/…/的插值。因为各方面的原因,用字符串构建正则表达式比regex对象要麻烦得多,比如在这个例子中,必须记住$WordRegex必须和/x一起使用才行。
我们也可以只使用字符串解决这个问题,只需要在表达式中设定模式修饰范围(☞135):
此时,m/…/的正则文字插值之后,正则引擎接收到「^((?x:/b·/w+·/b))」,这就是我们期望的结果。
其实这就是生成regex对象的逻辑过程,只是regex对象对于每个模式修饰符,都明确定义了“on”或“off”的状态。用qr//b·/w+·/b/x生成「(?x-ism:/b·/w+·/b)」。请注意模式修饰符的设定「(?x-ism:…)」,这里启用了/x,禁止了/i、/s和/m。也就是说,无论是否指定qr/…/的修饰符,regex对象总是“锁定”在某个模式下。
探究regex对象
Viewing Regex Objects
前面讨论了regex对象综合正则表达式和模式修饰符——例如「(?x-ism:…)」——的逻辑过程。如果在Perl期望接收字符串的地方使用regex对象,Perl会把它转换为对应的文本表示方式,例如:
这就是第304页的$HttpUrl的转换结果:
把regex对象转换为字符串的功能在调试时很有用。
用regex对象提高效率
Using Regex Objects for Efficiency
使用regex对象的主要原因之一是便于控制。为了提高效率,Perl会把正则表达式编译为内部形式。第6章简要介绍了正则表达式编译的一般知识,但是更复杂的Perl相关问题,包括 regex 对象之类,都在“正则表达式编译、/o 修饰符、qr/…/和效率”(☞348)中详细讨论。