正则表达式如何处理嵌套结构
1,正则表达式如何处理嵌套结构
a.处理嵌套结构的⽅法
举例说明:
问题描述:从before (nope (yes (here) okay) after中匹配得到最⼤的被”()”包含的⽂本。即显⽰红⾊的部分。
答案::"((?>[^()]+|"((?<DEPTH>)|")(?<-DEPTH>))*(?(DEPTH)(?!))")
分析:
(1)、"(匹配左括号;")匹配右括号;[^()]+匹配⾮括号字符串
正则表达式获取括号内容(2)、(?>….)固化分组,固化分组的作⽤在于:⼀旦括号内的⼦表达式匹配之后,匹配的内容就固定下来,在接下来的匹配过程中不会
改变,除⾮整个固化分组的括号都被弃⽤,在外部回溯中重新应⽤。该处使⽤固化分组的作⽤在于提⾼
匹配速度。
(3)、DEPTH的使⽤:DEPTH实际使⽤了命名捕获的<?>…>,它总是能够匹配成功。正则表达式引擎的回溯堆栈保存了当前匹配成功
分组的相关信息,⽽(?<DEPTH>)跟在"(后,所以它的成功匹配便可以保存"(的个数。跟随在")后的结构(?<-DEPTH>)是.NET独有的结构,它会在匹配")成功之后去掉最近的”successful DEPTH”标记。如果不存在这样的”successful DEPTH”标记,就会报告失败,整个正则表达式匹配失败:1,每匹配⼀个"(会把正则表达式保存的当前括号嵌套深度值加1;2, 每匹配⼀个")会把正则表达式保存的当前括号嵌套深度值减1;3, (?(DEPTH)(?!))确保匹配最后的")时,深度为0。
2,如何使⽤正则表达式处理句法分析树
如何使⽤正则表达式识别⼀棵类似如下表⽰的句法分析树?
(TOP (S (NPB (DT The) (NN question) ) (VP (VBZ remains) (SBAR-A (IN whether) (S-A (NPB (PRP they) ) (VP (MD will) (VP-A (VB be) (ADJP (JJ able) (SG (VP (TO to) (VP-A (VB help) (PUNC. us.) ) ) ) ) ) ) ) ) ) ) )
答案:"((?>[^()]+|"([^()"s]+"s(?<DEPTH>)|")"s(?<-DEPTH>))*(?(DEPTH)(?!))")
分析类似。
3,使⽤正则表达式处理句法分析树实例
a.使⽤正则表达式获取所有的叶结点: "((?<POS>[^()]+)"s(?<Leaf>[^()]+)")
b.使⽤正则表达式获取所有的名词短语NP:
"(NP"s(?>[^()]+|"([^()"s]+"s(?<DEPTH>)|")"s(?<-DEPTH>))*(?(DEPTH)(?!))")
c.使⽤正则表达式获取满⾜如下性质的⼦树
i. 该⼦句的标记为SBAR[^()]*
ii. 该⼦句根节点的第⼀个⼉⼦为⼀个词性为IN的词。
iii. 该⼦句的第⼆个⼉⼦为⼀个⼦句:使⽤S[^()]*识别
iv. 该⼦句没有其他的⼉⼦
(?<Clause>"(S[^() ]*"s(?<INWH>"(IN"s[^()]+")"s)(?<ClauseAfterInWh>"(S[^() ]*"s(?>[^()]+|"([^()"s]+"s(?
<DEPTH>)|")"s(?<-DEPTH>))*(?(DEPTH)(?!))")"s)")"s(?#Clause)) 在开发模板引擎时遇到了⼀个⽤正则表达式⽐较难以处理的情况,就是⽆限级的嵌套结构的匹配。HTML标签就属于这种结构。
举个具体的例⼦,下⾯是我们要匹配的内容:
1
2 3 4 5<x>
<x></x>
<y></y>
</x>
<x></x>
在到⽤正则匹配⽆限层嵌套结构的⽅法之前,我只能绕弯路来实现对⽆限层嵌套结构的匹配。
我只能⽤正则先把每个独⽴的标签匹配出来,然后⽤第⼀个标签名x做参数,逐⼀的查匹配出来的每⼀个独⽴标签,看看他是否是第⼀个x对应的闭合标签。
这种⽅式得加上判断嵌套层次的代码,还得匹配和循环很多没有⽤的数据。
后来我才了解到.NET提供了⼀个正则表达式的扩展特性,⽤来帮助处理⽆限层嵌套结构的匹配。这种特性是.NET特有的,别的编程语⾔或者平台不⼀定会有。
我们都知道正则的匹配组的概念,它的语法是 (?<;组名>)。使⽤这个正则语法我们可以建⽴⼀个匹配组。其实这是⼀个⼊栈的过程。⽽.NET对正则的匹配组做了⼀个特殊的⽀持 (?<-组名>)。使⽤这个正则语法我们可以将指定组名的最后匹配结果去除。也就是出栈了。⼀个⼊栈⼀个出栈,这⼀⼊⼀出就为我们提供了匹配⽆限层嵌套的可能
下⾯举个例⼦看看怎么实现⽆限层嵌套的匹配:
从图中我们可以看出正则正确的匹配出了最顶层的三个<x></x>结构,⽽嵌套在第⼆个<x></x>结构中的标签被当成了结构的内容。这是怎么做到的呢?
下⾯是图中的正则,我加⼊了注释:
1
2 3 4 5 6 7 8 9 10<x>
(?>
<x>(?<n>) #在匹配到<x>时,将匹配组n⼊栈
|
</x>(?<-n>) #在匹配到</x>时,将匹配组n出栈
|
(?!<x>|</x>). #匹配除<x>和</x>以外的其他字符
)*
(?(n)(?!)) #如果执⾏到此处还存在匹配组n,则匹配失败,重新匹配 </x>
这段正则中还⽤到了平时⽐较少使⽤到的(?!(name)yes|no)语法,这个语法相当于C语⾔的if语法,⽤于做条件判断,之⽤。上⾯的正则中我们⽤它来⽚段是否存在命名组n,如果存在命名组n,说明标记没有对称闭合,⽤(?!)断⾔匹配失败,重新匹配。
在《Mastering Regular Expressions》中似乎有相关章节提到这种⽆限层嵌套结构的匹配,不过我⼿
头没这本书。我是从学习到这种特殊的正则语法的,⼤家可以参考下
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论