perl–通用量词​&优先级&优先级范例&模式测试程序

十四、通用量词

模式中的量词(quantifier)代表前面条目的重复次数。到目前为止,我们已经见过三个量词:*+以及?。如果这三个量词都不符合需要,你还可以使用花括号({})的形式指定具体的重复次数范围

因此,模式/a{5,15}/可匹配重复出现5到15次的字母a。如果a连续出现3次,则不匹配。因为次数太少了;若a出现5次,就会匹配成功;出现10次时,也会匹配成功。因为15是上限,所以如果a出现20次,就只有前15个会匹配。

如果省略第二个数字但保留逗号,则表示匹配次数没有上限。所以,/(fred){3,}/这个模式会匹配重复出现3次以上的fred(在每个fred之间不能有空格等额外字符)。因为没有上限,所以即使字符串里有88个fred,也会匹配成功。如果同时省略逗号与上限次数,那么花括号里的数字就表示一个固定的次数:/ w{8}/会匹配正好有8个单词字符的字符串(或许是大型字符串里的一部分),而/,{5} chameleon/所匹配的就是“comma comma comma comma commma chameleon”。

事实上,我们之前提到的三个量词字符都只是常用的简写而已。星号量词{0,}相同,表示零次或多次加号相当于{1,}表示一次以上。然后,问号也可以写成{0,1}。因为这三个简写几乎能满足绝大多数的需求,所以平时不太会需要花括号量词。

十五、优先级看完正则表达式中这一大堆的元字符,你可能会觉得需要一张记分卡帮助整理思路。确实有一张优先级表,它告诉我们模式中哪些部分的“紧密度”最高。不像操作符的优先级表,正则表达式的优先级表相当简单,只有4个级别。我们这里顺便复习–下Perl模式中使用的元字符。对于表8-1所展示的优先级顺序,大致阐释如下:

1.最高等级是圆括号(“()”),用于分组和捕获。圆括号里的东西总是比其他东西更富有紧密性。

2. 第二级是量词,也就是重复操作符:星号(*)、加号(+)、问号(?),以及使用花括号表示的量词,比如{5,15}、{3,}和{5}。它们都会和它前面的条目紧密相连。

3.第三级是锚位和序列。我们已经介绍过的锚位有:A、Z、z、^、$、b和B。序列(彼此相邻的条目)事实上也是操作符,就算没有使用元字符也是如此。这就是说,单词里字母之间的紧密程度和锚位与字母之间的紧密程度是相同的。

4.第四级是择一竖线(|)。由于它位于优先级表底部,所以从效果上来看,它会把各种模式拆分成数个组件。另外,择一竖线的优先级之所以放在锚位与序列的下面,是因为我们希望类似/fred|barney/的模式中,单词里的字母间的紧密程度高于择一竖线。否则,该模式的解释方式就成了“匹配fre,后面所跟的字母必须是d或者b,然后再跟arney”。所以,择一竖线位于优先级表的底部,这样单词里的字母才会紧密连接在一起,成为一个整体。

5.最低级别的称为原子(atoms)。正是由这些原子构成了大多数基本的模式,比如单独的字符、字符集以及反引用等等。

图片

十六、优先级范例

当你需要解读相当复杂的正则表达式时,你就得照着Perl的方式,使用优先级表按部的班地进行分析。

举例来说,/Afred|barneyz/大概不会是程序员想要的模式。因为择一竖线的优先场比较低,这样整个模式就会被拆成两半。这个模式要么匹配字符串开头的fred,要么配字符串结尾的barney。程序员实际想要的多半是/A(fred|barney)z/,也就是匹配包含fred或只包含barney的每一行。那么,模式/(wilma|pebbles?)/该怎么理解呢?实际上,那个问号量词仅仅对接在前面的字符起作用,所以这个模式可匹配到willma、pebbles以及pebble这三个字符串,或是长字符串中的一小部分(因为模式中没有锚位)。

模式/A(w+)s+(w+)z/可用来匹配开始是一个单词,再来是一些空白,然后又是一个单词(前面或后面没有其他东西)的行。举例来说,它大概就是用来匹配fred flintstone之类的字符串。这里的圆括号并不是为了分组而存在,可能只是为了把匹配的字符串捕获下来

在尝试理解一个很复杂的模式时,试着加上一些圆括号会对弄清优先级有好处但请记住,圆括号同时也会有捕获的效果。因此建议尽可能用非捕获圆括号来分组

十七、模式测试程序

编写Perl程序的时候,每个程序员都免不了要使用正则表达式,但有时候很难轻易看出一个模式能做什么事。而且常常会发现,模式匹配的范围总比预期的大些或小些。要不就是开始匹配的位置早些或晚些,要不就是根本无法匹配。


下面这个程序非常实用,可用于检测某些字符串是否能被指定模式匹配以及在什么位置上匹配:

#!usr/bin/perl -wuse strict;
while (<>) { chomp; if(/YOUR_PATTERN_GOES_HERE/) { print "Matched: |$`<$&>$'|n"; #特殊捕获变景 }else{ print "No match: |$_|n"; }}
图片

这个模式测试工具是给程序员使用的,而不是给最终用户,你一看便知分晓,因为并没有提示符,也没有用法说明。它会把所有输入一行行读进来,然后以你在YOUR_PATTERN_GOES_HERE指定的模式进行匹配。如果该行匹配模式,就会利用三个特殊的捕获变量($·、$&和$’)展示实际的匹配结果。假你使用的模式是/match/,而输入的字符串是beforematchafter,那么你会看到的程序输出就是|before<match>after|,尖括号里面的内容是字符串匹配模式的部分。如果结果跟你预想的不一样,马上就可以看出来。

 2022-05-02 16:08 发表于陕西

阅读原文

简介:生信小技能,欢迎关注微信公众号:生信小猪
(0)
打赏 喜欢就点个赞支持下吧 喜欢就点个赞支持下吧

声明:本文来自“生信小猪”,分享链接:https://www.zyxiao.com/p/309479    侵权投诉

网站客服
网站客服
内容投稿 侵权处理
分享本页
返回顶部