首页 > 代码库 > 正则表达式——量词
正则表达式——量词
【量词】,顾名思义就是用来匹配数量的。类似于\w,\d,[0-9]这样的元字符都只能匹配一个字符,如果要匹配多个字符就要输入此元字符多次,这样使用起来就很麻烦。所以正则表达式中使用了量词来进行【元字符】的数量的匹配,通过操作量词,可以匹配0个元字符,也可以匹配无数个元字符。在正则表达式中的量词分为三种,匹配优先量词(标准量词)、忽略优先量词、占有优先量词。此文着重描述匹配优先量词(标准量词),这类量词是在所有的正则表达式工具中都支持的量词,而忽略优先量词和占有优先量词则只在一部分正则工具中支持。其二会涉及一些忽略优先量词。对于占有优先量词,在此文中不涉及讲解,占有优先量词和固化分组的内容有关。
在上面提及的匹配优先量词)和忽略优先量词实际上也就是我们说的正则表达式中的贪婪模式和非贪婪模式,我们首先开始标准量词的讲解
匹配优先量词
匹配优先量词有那么几个*、+、?、{num,num},匹配优先的意思就是,它会尽可能多的匹配。我们先来简化一下熟悉一下每个量词的意义,所有的量词匹配都有一个所谓的上限和下限
*,星号的下限是【0】,上限是【无限】,这就意味着星号最少可以不匹配字符,最多可以匹配无数个字符
+,加号的下限是【1】,上限是【无限】,即加号最少必须匹配一个字符,最多可以匹配无数个字符
?,问好的下限是【0】,上限是【1】,即问好最少可以不匹配字符,最多能匹配一个字符
{num,num},这种结构可以被称作计数量词,它的上下线由表达式来控制,例如{5,10}代表着下限是【5】,上限是【10】,即最少要匹配5个字符,最多能匹配10个字符。
量词所匹配的内容是量词左边的元字符代表的内容,例如:
正则表达式:\d+
元字符\d表示一个数字,上面的正则表达式的意思就是,最少要匹配一个数字,最多可以匹配无数个相连的数字。假设文本为【1】,则能匹配成功,匹配内容为【1】。假设文本为【22334455】,也能匹配成功,匹配的文本的文本是【22334455】。假设文本为【1992年8月4日】,也能匹配成功,匹配出来的内容是【1992】【8】【4】三个内容
下面再举一个关于计数量词的例子
正则表达式:{5,10}
假设文本为【19920804】,则可以匹配成功,匹配文本为【19920804】。假设文本是【1992年8月4日】,则无法匹配成功,因为该正则最少需要匹配5个相连的字符,而在此文本中不存在这样的字符串。假设文本为【18722334455】,能匹配成功,匹配内容为【1872233445】,最后一个字符【5】没有匹配到的原因是该正则的上限是10,最多只能匹配10个相连的字符串
下面来举一个稍微有点难度的例子,这个例子涉及到一些正则表达式匹配原理的有关于交还的内容。
正则表达式:\d*3
上面这个正则表达式的意思是,不管匹配多少个数字字符,但是最后一个字符必须为3。假设文本为【11224455】,则匹配不成功,因为即使\d*能匹配所有的数字字符,但是最后的3无法找到对应匹配,所以匹配不成功。假设文本为【123456】,能匹配成功,匹配的文本为【123】。
那么对于这样的正则,匹配的时候是怎么进行的?这就要涉及到交换这个概念。交换的意思就是说,当在全文的匹配中(即完整的正则),当非必须匹配的(比如+,可以匹配1个,也可以匹配2个,所以匹配2个中的第二个也可以不用匹配,这就是非必须匹配)表达式遇上必须匹配的表达式时,必须匹配的表达式就会强迫非必须表达式进行交还。
在上面的例子\d*3中,非必须的表达式就是\d*,而必须的表达式就是3。在匹配文本【123456】的时候,\d*由于是匹配优先的,所以会匹配完所有的字符,匹配结果是【123456】,然后正则表达式推动到3,这时候3没有内容可以匹配了,所以强迫\d*交还出最后一位字符,即字符【6】与3进行匹配,无法匹配,继续交还,再交还字符【5】,还是无法匹配。如此循环一直交还到【3】,可以匹配。于是【完整的表达式】成立,匹配文本【123】。这就是整个匹配的过程。
忽略优先量词
忽略优先量词刚好与匹配优先量词相反,忽略优先量词的意思是尽可能少的匹配,即尽可能以匹配下限来匹配。忽略优先量词是*?、+?、??、{num,num}?他们的上下线和匹配优先量词一样,它们的结构也刚好是在匹配优先量词之后加上了一个【?】。下面先看一个例子:
正则表达式:ab??
正则表达式:假设文本是【ab】,上面的正则表达式所匹配的内容是【a】,因为它是忽略优先的,它匹配到【b】的时候,首先会选择忽略。而如果正则表达式是ab?,则匹配的文本会是【ab】,因为这时候的【b】是匹配优先的,它会首先选择匹配。这个例子说明了忽略优先和匹配优先的区别。再举一个稍复杂些的,也涉及到强迫交还概念的例子
正则表达式:ab??c
匹配的文本为【abc】,这里会匹配的结果是【abc】。匹配过程是这样的:首先正则a匹配字符【a】,可以匹配,继续往后,正则b??是忽略优先的,暂不匹配字符。继续往后,正则c匹配文本中的字符【b】(刚才没有进行过匹配,所以文本的指针记录还在文本b处),c与【b】无法匹配。这时候,并不会匹配失败,表达式的引擎会回溯到b??处,尝试与文本【b】匹配,可以匹配。继续正则c与字符【c】进行匹配,可以匹配,所以匹配的结果是【abc】。
上面这个例子中提到一个新的概念回溯,回溯是只有在NFA引擎中才具备的功能,有关于NFA引擎和回溯,会在后续讲解。
参考:《精通正则表达式》