我的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)就行了那?这个是什么意思呢?

解决方案 »

  1.   

    <div[\S]*align="center"[\S]*>[\S]*</div>
      

  2.   

    Regex reg = new Regex(@"(?is)<div\s+align=""center"">(?:(?!</?div\b).)*</div>");
    Match m = reg.Match(yourStr);
    if (m.Success)
    {
        richTextBox2.Text = m.Value;
    }
      

  3.   

    (?s)是匹配模式,在.NET中相当于RegexOptions.Singleline
    也就是改变“.”的匹配范围,可以匹配任意一个字符而楼主的正则,在加了这个参数之后,由于是贪婪模式,所以会尽可能多的匹配,一直匹配到最后一个“</div>”也可以用非贪婪模式
    Regex reg = new Regex(@"(?i)<div\s+align=""center"">[\s\S]*?</div>");
    这样做一样能得到楼主想要的结果,但是在源字符串复杂时,效率会较低所以还是用环视+贪婪模式来实现,效率会高一些(?i)相当于RegexOptions.IgnoreCase,表示忽略大小写
      

  4.   


    string pattern=@"(?s)<div\s+align=""center"">.+?</div>"; Match m=Regex.Match(str,pattern);\s+ 匹配一个或多个空白字符
    用这个就对了,(?s)和你在选项里设置单行模式也就是RegexOptions.Singleline是一个意思
    .+  会匹配到最后一个 匹配优先.
    .+? 匹配尽可能少的文本.到第一个</div>结束 
      

  5.   

    那我询问下#4的高人,为什么不加(?s)一个都匹配不到呢?我感觉我正则没写错啊(?:(?!</?div\b).)*  这是什么意思呢?
      

  6.   

    LZ的问题我正好也遇到了,好奇地做了下。感觉C#的正则和python的正则有点区别
      

  7.   


    不加(?s)时,小数点“.”匹配除了换行符“\n”之外的任意一个字符,所以在不加(?s)时,只能匹配单行数据,可以用(.|\n)来匹配任意一个字符,但这样效率太低,可以用[\s\S]来匹配任意一个字符,但效率最高的,还是(?s)加.来实现,当然,.NET中是这样的,其它语言,效率表现可能会有所不同
      

  8.   

    我现在是这么写的
    string trackPattern = @"<div\s+id=""m_track""\s+class=""modbox"">(.|\n)*</div>";
    不用贪婪的,但是匹配到的还是2个div...改进的办法有吗?觉得4#有点繁琐啊
      

  9.   

    (?:(?!</?div\b).)*  比如要匹配HTML标签,可以用
    <[^>]*>
    其中[^>]*就是排除型字符组,但它仅能排除单个的字符,而不能排除一个子字符串,要排除子字符串,可以使用环视
    ((?!</?div\b).)*
    就表示任意多个右侧不是<div或</div的字符
    <div\s+align=""center"">(?:(?!</?div\b).)*</div>
    用在这里也就表示从<div开始,到第一个</div>之间的内容
      

  10.   

    量词“*”仍然是贪婪的
    string trackPattern = @"<div\s+id=""m_track""\s+class=""modbox"">(.|\n)*?</div>";正则的效率高低不在于形式上是否繁琐,如果你认为书写简单的,就是效率高的,劝你不要用正则了
      

  11.   

    上面的“?” 错了,输入法没切换,应该是半角的string trackPattern = @"<div\s+id=""m_track""\s+class=""modbox"">(.|\n)*?</div>";
    关于匹配任意字符效率的讨论,我之前整理了一下
    正则基础之——小数点 
      

  12.   

    奇怪啊,为什么这样得到的还是2个div?            string trackPattern = @"(?s)<div\s+align=""center"">(?:(?! </?div\b).)*</div>";
      

  13.   

    (?s)<div\s+align="center">.+?</div>

    <div\s+align="center">(?:(?! </?div\b).)* </div> 理论上第二个快一些,实际上差别不大,100毫秒以内,.net会对部分正则进行优化
    环视还没到数量级的优势啊 这个3000行以内的文本,差别不到0.1秒.都是在0.0x秒内执行 看需求了
      

  14.   

    其实正则匹配效率,在匹配成功的情况下,效率不会有很大差别的
    效率的差别更多的在于,匹配失败的情况下,是否能以最快的速度报告失败
    其实上面的正则,还可以通过固化分组来提升效率
    Regex reg = new Regex(@"(?is)<div\s+align=""center"">(?>(?:(?!</?div\b).)*)</div>");
    只是这样做了以后,可读性更差,更难于理解罢了