我的html代码是这样的
<div align="center">
<p class=g> <a href="#">avi</a><br> <font size=-1>Size <br> Type </font><br> <font color=#008000 size="1">E659A37C3B6B49CEAC0898EAB8C88853</font></font>
<p class=g> <a href="#">avi</a><br> <font size=-1>Size <br> Type </font><br> <font color=#008000 size="1">E659A37C3B6B49CEAC0898EAB8C88853</font></font>
</div>
<div>
<table cellpadding="0" cellspacing="0"> <tr> <td valign="bottom">
<span class="g"><span class="Estilo1"><font size=-1>page:</font></span></span> </td> <td> <br> 0</a></td> <td> <a > <br> 1</a></td> <td> <a href="search.php?> <br> 2</a></td> <td> <a href="search.php?> <br> 3</a></td> <td> <a href="search.php?> <br> 4</a></td> <td> <a href="search.php?> <br> 5</a></td> <td> <a href="search.php?> <br> 6</a></td> <td> <a href="search.php?> <br> 7</a></td> <td> <a href="search.php?> <br> 8</a></td> <td><a href="search.php?><br> <strong>Next </strong></a></td> </tr> </table>
</div>
我想通过正则表达来抽取 <div align="center">
<p class=g> <a href="#">avi</a><br> <font size=-1>Size <br> Type </font><br> <font color=#008000 size="1">E659A37C3B6B49CEAC0898EAB8C88853</font></font>
<p class=g> <a href="#">avi</a><br> <font size=-1>Size <br> Type </font><br> <font color=#008000 size="1">E659A37C3B6B49CEAC0898EAB8C88853</font></font>
</div>
这段内容,所以我写了个正则表达式: string pattern=@"<div align=""center"">.+</div>";
Match m=Regex.Match(str,pattern);结果居然取不到?
别人告诉我前面要加个(?s),也就是string pattern=@"(?s)<div align=""center"">.+</div>";
Match m=Regex.Match(str,pattern);
我按他说的做了,结果匹配到了,但是获得的居然是2个div都得到了,也就是第一段代码的所有内容,可我要的只是第一个div的代码,该怎么办?
还有帮我解释下为什么正则表达式前面加个(?s)就行了那?这个是什么意思呢?
<div align="center">
<p class=g> <a href="#">avi</a><br> <font size=-1>Size <br> Type </font><br> <font color=#008000 size="1">E659A37C3B6B49CEAC0898EAB8C88853</font></font>
<p class=g> <a href="#">avi</a><br> <font size=-1>Size <br> Type </font><br> <font color=#008000 size="1">E659A37C3B6B49CEAC0898EAB8C88853</font></font>
</div>
<div>
<table cellpadding="0" cellspacing="0"> <tr> <td valign="bottom">
<span class="g"><span class="Estilo1"><font size=-1>page:</font></span></span> </td> <td> <br> 0</a></td> <td> <a > <br> 1</a></td> <td> <a href="search.php?> <br> 2</a></td> <td> <a href="search.php?> <br> 3</a></td> <td> <a href="search.php?> <br> 4</a></td> <td> <a href="search.php?> <br> 5</a></td> <td> <a href="search.php?> <br> 6</a></td> <td> <a href="search.php?> <br> 7</a></td> <td> <a href="search.php?> <br> 8</a></td> <td><a href="search.php?><br> <strong>Next </strong></a></td> </tr> </table>
</div>
我想通过正则表达来抽取 <div align="center">
<p class=g> <a href="#">avi</a><br> <font size=-1>Size <br> Type </font><br> <font color=#008000 size="1">E659A37C3B6B49CEAC0898EAB8C88853</font></font>
<p class=g> <a href="#">avi</a><br> <font size=-1>Size <br> Type </font><br> <font color=#008000 size="1">E659A37C3B6B49CEAC0898EAB8C88853</font></font>
</div>
这段内容,所以我写了个正则表达式: string pattern=@"<div align=""center"">.+</div>";
Match m=Regex.Match(str,pattern);结果居然取不到?
别人告诉我前面要加个(?s),也就是string pattern=@"(?s)<div align=""center"">.+</div>";
Match m=Regex.Match(str,pattern);
我按他说的做了,结果匹配到了,但是获得的居然是2个div都得到了,也就是第一段代码的所有内容,可我要的只是第一个div的代码,该怎么办?
还有帮我解释下为什么正则表达式前面加个(?s)就行了那?这个是什么意思呢?
Match m = reg.Match(yourStr);
if (m.Success)
{
richTextBox2.Text = m.Value;
}
也就是改变“.”的匹配范围,可以匹配任意一个字符而楼主的正则,在加了这个参数之后,由于是贪婪模式,所以会尽可能多的匹配,一直匹配到最后一个“</div>”也可以用非贪婪模式
Regex reg = new Regex(@"(?i)<div\s+align=""center"">[\s\S]*?</div>");
这样做一样能得到楼主想要的结果,但是在源字符串复杂时,效率会较低所以还是用环视+贪婪模式来实现,效率会高一些(?i)相当于RegexOptions.IgnoreCase,表示忽略大小写
string pattern=@"(?s)<div\s+align=""center"">.+?</div>"; Match m=Regex.Match(str,pattern);\s+ 匹配一个或多个空白字符
用这个就对了,(?s)和你在选项里设置单行模式也就是RegexOptions.Singleline是一个意思
.+ 会匹配到最后一个 匹配优先.
.+? 匹配尽可能少的文本.到第一个</div>结束
不加(?s)时,小数点“.”匹配除了换行符“\n”之外的任意一个字符,所以在不加(?s)时,只能匹配单行数据,可以用(.|\n)来匹配任意一个字符,但这样效率太低,可以用[\s\S]来匹配任意一个字符,但效率最高的,还是(?s)加.来实现,当然,.NET中是这样的,其它语言,效率表现可能会有所不同
string trackPattern = @"<div\s+id=""m_track""\s+class=""modbox"">(.|\n)*</div>";
不用贪婪的,但是匹配到的还是2个div...改进的办法有吗?觉得4#有点繁琐啊
<[^>]*>
其中[^>]*就是排除型字符组,但它仅能排除单个的字符,而不能排除一个子字符串,要排除子字符串,可以使用环视
((?!</?div\b).)*
就表示任意多个右侧不是<div或</div的字符
<div\s+align=""center"">(?:(?!</?div\b).)*</div>
用在这里也就表示从<div开始,到第一个</div>之间的内容
string trackPattern = @"<div\s+id=""m_track""\s+class=""modbox"">(.|\n)*?</div>";正则的效率高低不在于形式上是否繁琐,如果你认为书写简单的,就是效率高的,劝你不要用正则了
关于匹配任意字符效率的讨论,我之前整理了一下
正则基础之——小数点
和
<div\s+align="center">(?:(?! </?div\b).)* </div> 理论上第二个快一些,实际上差别不大,100毫秒以内,.net会对部分正则进行优化
环视还没到数量级的优势啊 这个3000行以内的文本,差别不到0.1秒.都是在0.0x秒内执行 看需求了
效率的差别更多的在于,匹配失败的情况下,是否能以最快的速度报告失败
其实上面的正则,还可以通过固化分组来提升效率
Regex reg = new Regex(@"(?is)<div\s+align=""center"">(?>(?:(?!</?div\b).)*)</div>");
只是这样做了以后,可读性更差,更难于理解罢了