Kontext Copilot - An AI assistant for data analytics. Learn more
Expression of Interest
浅谈正则表达式匹配嵌套HTML标签
insights Stats
warning Please login first to view stats information.
Raymond
.NET Programming
Everything about .NET framework, .NET Core, .NET Standard, .NET 5 and .NET 6.
在.NET中我们可以很容易的使用Regex
类创建正则表达式对象,用于匹配、替换、筛选数据等,对于文本处理是非常有用的。
由于时间关系,本文不对正则表达式本身作介绍,而仅分析嵌套匹配的正则表达式作简单的分析。
一,匹配单一的嵌套标签
这种情况是比较简单的,因为只是匹配单一的嵌套标签,比如:
<div>我是一层<div> </div> <div class="test"> 我是二层div <div class="test"> 我是三层div</div></div> <div class="test"> 我是二层div</div> <div class="test"> 我是二层div</div> </div>
我们可以看出,在上面的HTML片断中只有div标签,那么正则表达式可以写成:
<div[^>]*>[^<>]* #匹配开始div以及非标签内容 ( ( (?'Open'<div[^>]*>)[^<>]*)+ #匹配开始div标签 ((?'-Open'</div>)[^<>]*)+ #匹配结束div标签 )* (?(Open)(?!)#如果堆栈上还有匹配组Open则匹配失败 ) </div> #匹配结尾div
在Regex Tester中测试结果:
如果我们在标签中添加<p></p><ul></ul>
等其它标签那么匹配就会失败了,不能匹配最外层的div标签。
二,修改的嵌套div正则,可包含其它标签
将HTML修改为:
<div>我是一层<div> </div><ul></ul> <div class="test"> 我是二层div <div class="test"> 我是三层div</div></div> <div class="test"> 我是二层div</div> <div class="test"> 我是二层div</div> </div>
正则表达式修改为:
<div[^>]*> #开始div标签 (?<tagcontent> #将div标签之间的所有内容捕获到组tagcontent中 (.|\n)*? #匹配任意字符或者换行符但是尽量少 ( ( (?'Open'<div[^>]*>) #匹配嵌套的div开始标签 (.|\n)*? #匹配开始div标签后的内容 )+ #匹配至少一个div开始标签,开始标签后面可以不跟任何内容也可以包含其它标签 ( (?'-Open'</div>) #匹配嵌套的div闭合标签 (.|\n)*? #匹配闭合div标签后的内容 )+ #匹配至少一个div闭合标签,闭合标签后面可以不跟任何内容也可以包含其它标签 )* #开始标签和闭合标签匹配0次或者以上的情况 (?(Open)(?!))#如果堆栈上还有组名为Open的项则匹配失败 ) </div> #结束div标签
在Regex Tester中测试结果为:
三,其它的相关说明
在二中,如果我们在html中多添加一个<div>标签或者在结束前添加一个</div>标签,那么整个html不是valid的xhtml,比如:
<div>我是一层<div><div> </div><ul></ul> <div class="test"> 我是二层div <div class="test"> 我是三层div</div></div> <div class="test"> 我是二层div</div> <div class="test"> 我是二层div</div> </div>
在上述中,如果将正则中(?(Open)(?!))
注释掉,那么会多一个匹配组Open
,且其内容为<div>
,如果不注释那么匹配组Open
的内容就会是一个位置而已,其Index为0,Length为0。
如果HTML为:
<div>我是一层<div> </div><ul></ul> <div class="test"> 我是二层div <div class="test"> 我是三层div</div></div> <div class="test"> 我是二层div</div> <div class="test"> 我是二层div</div></div> </div>
那么最后一个多余的</div>
不会匹配上。
有一点在参考文章中也有提到,这里再次强调下:
其中(?<-N>)
是表示释放之前捕获的N
分组。确切的语法是(?<N-M>)
即使用N
分组替换掉M
分组,如果N
分组没有指定或不存在,则释放M
分组。
参考文档
info Last modified by Raymond 3 years ago
copyright
This page is subject to Site terms.
comment Comments
No comments yet.