首页 > 代码库 > 正则表达式(四)——位置匹配(环视、单词分界符、锚点)
正则表达式(四)——位置匹配(环视、单词分界符、锚点)
这次的内容是有关于正则表达式中的位置匹配,它包含的内容有两部分,一部分是较为简单的锚点和单词分界符,一部分是较为复杂的零宽断言。复杂有复杂的好处,写起来复杂,能匹配的位置也就越复杂。零宽断言又可以叫做环视。这一部分是重点内容。
锚点
标准的锚点有这么几个,它们是^,$。在普遍的,不涉及任何模式的情况下,脱字符(^)匹配的是文本的起始位置。而$匹配的则是文本末尾的换行符\n之前的位置。举个例子
正则表达式:s$
上面这个正则表达式的意思就是匹配以字符【s】结尾的行,即【······s/n】这样的字符串。
单词分界符
单词分界符在不同的工具中支持也不同,一般来说,支持最好的是\b,其次有的工具还支持\<、\>。\b匹配单词的边界,即可以匹配单词的起始,也可以匹配单词的结束。而\<、\>则分别匹配单词的开始位置和结束位置。这个元字符是很简单的。不过对于每种工具它所定义的“单词字符”的含义都不一样,导致可能不同的工具,单词分界符能匹配到的内容有所差异。不过一般来说,只要是一个正常的单词,类似【happy】、【new】之类的单词是必定能匹配的。单词分界符并不会对单词进行语义的分析,它的规则通常只是简单的相连字符,所以类似【a1d2c3d4】这样的文本,单词分界符也能成功匹配。但是有可能像【I.T】这样的单词就无法成功匹配了。
环视(零宽断言)
环视又叫零宽断言。依照字面意思可以这样理解:零宽即匹配到的宽度为0(匹配到1个字符的话宽度就是1了,匹配位置的话无法匹配到任何字符,宽度为0),断言即需要满足一定的条件。所以零宽断言是意思就是:在一定的条件下匹配到的位置。
环视分两类(顺序、逆序)四种,它们是
【顺序肯定环视(?=Expression)】
【顺序否定环视(?!Expression)】
【逆序肯定环视(?<=Expression)】
【顺序否定环视(?<!Expression)】
顺序环视就是从左边向右匹配,逆序的就是从右边向左匹配。但是逆序的使用就现在的正则表达式而言,有所限制,此限制放到最后讲。我们首先从环视的匹配基础上讲起。
对于顺序肯定环视(?=Expression)来说,子表达式(即除?=以外的表达式)Expression匹配右边的字符成功时,表达式(?=Expression)匹配成功,并报告引擎在当前位置匹配成功。当Expression匹配右边的字符失败时,表达式(?=Expression)匹配失败。
对于顺序否定环视(?!Expression)来说,子表达式(即除?!以外的表达式)Expression匹配右边的字符失败时,表达式(?!Expression)匹配成功,并报告引擎在当前位置匹配成功。当Expression匹配右边的字符成功时,表达式(?!Expression)匹配失败。
对于逆序肯定环视(?<=Expression)来说,子表达式(即除?<=以外的表达式)Expression匹配左边的字符成功时,表达式(?<=Expression)匹配成功,并报告引擎在当前位置匹配成功。当Expression匹配左边的字符失败时,表达式(?<=Expression)匹配失败。
对于逆序否定环视(?<!Expression)来说,子表达式(即除?<!以外的表达式)Expression匹配左边的字符失败时,表达式(?<!Expression)匹配成功,并报告引擎在当前位置匹配成功。当Expression匹配左边的字符成功时,表达式(?<!Expression)匹配失败。
下面举几个例子,例子来源于网络,首先是一个顺序否定环视的例子。
源字符串:aa<p>one</p>bb<div>two</div>cc
正则表达式:<(?!/?p\b)[^>]+>
这个正则的意义就是匹配除了<p···>或</p>之外的所有标签
按图所示,这个正则中<就匹配它本身,(?!/?p\b)是一个顺序否定表达式,子表达式是</?p\b,意思是这个表达式的右边不能是字符【/p】或者【p】,问号是代表匹配一次或者不匹配,大家应该还记得。然后[^>]+中的[^···]是排除型字符组,表示的是除【>】以外的字符都可以匹配,匹配的数量是最少一次,最多不限制。最后一个表达式>的意义是匹配它本身。
上面整个表达式的含义就是:匹配【<(<右边不能是p或/p)(除>的字符N个)>】这样一个文本。由此例子,我们也可以看出,表达式通常可以拆分成一个个的子表达式,最后把它们连起来形成一个完整的表达式。
再看一个逆序肯定环视的例子
源字符串:<div>a test</div>
正则表达式:(?<=<div>)[^<]+(?=</div>)
这个正则的意义就是匹配<div>和</div>标签之间的内容,而不包括<div>和</div>标签本身。
(?<=<div>) 的意思就是左边不能是<div>,而(?=</div>) 的意思是右边不能是</div>。
具体上面两个例子的执行步骤,感兴趣的请看参看的第二篇引用。我们现在回过头来讲一讲逆序环视的限制。逆序环视使用的必要条件是:逆序环视只能在有限长度的文本中使用。意思就是表达式能匹配的文本必须长度必须是有限的,如果表达式是(?<!books?) 或者(?<!\w+)则无法匹配,因为它们的长度无法确定。因为此原因,也有一些工具不支持逆序环视
参考:《精通正则表达式》
《正则基础之——环视》