.net中的正则表达式使用高级技巧 (三)

上篇:
.net中的正则表达式使用高级技巧 (一)
.net中的正则表达式使用高级技巧 (二)

反向引用

反向引用,指把匹配出来的组引用到表达式本身其它地方,比如,在匹配HTML的标记时,我们匹配出一个<a>,我们要把匹配出来的a引用出来,用来找到</a>,这个时候就要用到反向引用。
语法
    a、反向引用编号的组,语法为\number
    b、反向引用命名的组,语法为\k<name>
举例
    a、匹配成对的HTML标签

@"<(?<tag>[^\s>]+)[^>]*>.*</\k<tag>>"        

    b、匹配两个两个重叠出现的字符  

        public static void Main()
        
{    
            
string s = "aabbc11asd";
            Regex reg 
= new Regex(@"(\w)\1");
            MatchCollection matches 
= reg.Matches(s);
            
foreach(Match m in matches)
                Console.WriteLine(m.Value);
            Console.ReadLine();
        }
      

返回结果为aa bb 11 

辅助匹配组

以下几种组结构,括号中的Pattern都不作为匹配结果的一部分进行保存
    1、正声明(?=)
    涵义:括号中的模式必须出现在声明右侧,但不作为匹配的一部分

        public static void Main()
        
{    
            
string s = "C#.net,VB.net,PHP,Java,JScript.net";
            Regex reg 
= new Regex(@"[\w\#]+(?=\.net)",RegexOptions.Compiled);
            MatchCollection mc 
= reg.Matches(s);
            
foreach(Match m in mc)
                Console.WriteLine(m.Value); 
            Console.ReadLine();
            
//输出 C# VB JScript
        }

    可以看到匹配引擎要求匹配.net,但却不把.net放到匹配结果中
    2、负声明(?!)
     涵义:括号中的模式必须不出现在声明右侧
        下例演示如何取得一个<a>标签对中的全部内容,即使其中包含别的HTML tag

        public static void Main()
        

            
string newsContent = @"url:<a href=""1.html""><img src=""1.gif"">test<span style=""color:red;"">Regex</span></a>.";
            Regex regEnd 
= new Regex(@"<\s*a[^>]*>([^<]|<(?!/a))*<\s*/a\s*>",RegexOptions.Multiline);
            
            Console.WriteLine(regEnd.Match(newsContent).Value);
//Result: <a href="1.html"><img src="1.gif">test<span style="color:red;">Regex</span></a>
            Console.ReadLine();
        }

    3、反向正声明(?<=) 
    涵义:括号中的模式必须出现在声明左侧,但不作为匹配的一部分
    4、反向负声明(?<!)
    涵义:括号中的模式必须不出现在声明左侧

非回溯匹配
语法:(?>)
涵义:该组匹配后,其匹配的字符不能通过回溯用于后面的表达式的匹配。呵呵,光看这句话肯定搞不懂,我当初为了搞懂这个也花了不少的时间,还是通过实例来说明吧:
"www.csdn.net" 可以通过@"\w+\.(.*)\.\w+"来匹配,却不能通过@"\w+\.(?>.*)\.\w+"来匹配!为什么呢?

原因是正则匹配是贪婪的,匹配时它会尽可能多的匹配最多的结果,所以,上例两个正则式中的.*都会把csdn.net匹配完, 这个时候,第一个表达式在开始匹配时发现\.\w+没得字符给它匹配了,所以它会进行回溯,所谓回溯,就是把.*匹配的结果往回推,回推留出来的字符再用来匹配\.\w+,直到\.\w+匹配成功,整个表达式返回成功的匹配结果。而第二个表达式,因使用的是非回溯匹配,所以,.*匹配完后,不允许通过回溯来匹配\.\w+,所以整个表达式匹配失败。

请注意,回溯匹配是很浪费资源的一种匹配方式,所以,请尽量避免您的正则式要通过回溯来成功匹配,如上例,可以换成@"\w+\.([^\.]+\.)+\w+"+"

下一篇:.net中的正则表达式使用高级技巧 (四)

posted @ 2006-03-02 10:45 Lyn 阅读(5276) 评论(17)  编辑 收藏 所属分类: Regex expression

  回复  引用  查看    
#1楼 2006-03-02 12:59 | 装配脑袋      
好难懂啊@_@
  回复  引用  查看    
#2楼 [楼主]2006-03-02 13:17 | THIN      
看看示例代码可能好懂点
不知哪处难懂
  回复  引用  查看    
#3楼 2006-03-02 13:31 | 潘成勇      
@装配脑袋

  回复  引用    
#4楼 2006-03-02 14:49 | vender [未注册用户]
(?>)主要是为了提高性能,在正则式语义表达方面作用不大

不同的正则式匹配引擎关于(?<=re)和(?<!re)的实现略有不同,例如perl、python等要求re必须是fixed-width的,pcre等允许re是由几个fixed-width组成的alternation,.net和java中的regex在这方面能力较强,对re没什么要求

  回复  引用  查看    
#5楼 [楼主]2006-03-02 20:43 | THIN      
(?>)还是有其作用的。
明天讲完lazy匹配,判断式和引擎特点,全文就完了。
  回复  引用  查看    
#6楼 2006-03-03 10:24 | birdshome      
对,那个什么xxx就是没事找抽型,越搭理他它越来劲的说
  回复  引用  查看    
#7楼 [楼主]2006-04-03 16:34 | THIN      
@浪子
之所以要加上|<(?!/a))*,是因为<a>中可能有<img之类的元素,这些元素也以<开头,但它们也是<a>的子元素,所以不能简单的认为,只要有<,结束标记就开始了
  回复  引用  查看    
#8楼 2006-04-19 19:05 | 达达      
收益不小,好文!
  回复  引用    
#9楼 2006-05-05 12:37 | mendel [未注册用户]
虽然看的不太懂,但是还是从里面学到了很多,谢谢楼主~~~
  回复  引用  查看    
#10楼 2006-05-13 13:32 | 维生素C.NET      
Thin您好,很想知道知道对于这个问题的逻辑,使用正则表达式能否有更为清晰的思路的或更高的效率,谢谢您.
文章地址:http://www.cnblogs.com/lovewangshu/archive/2006/05/13/398894.html
  回复  引用  查看    
#11楼 2006-08-15 23:04 | 阿贵      
我还有一个类似的问题,不知你是否愿意帮我看一下:
string pattern ="";
Regex r=New Regex(pattern,RegexOptions.Multiline);
MatchCollection mc=r.Matches(WebpageSourceCode);

我相从网页source code中提取这些信息:以<a href="personen.d4w开头到第一个</tr>结束,网页中可能多个这样的字符串。不知第一行的那个pattern该怎么写?

如果能得到帮助,将十分感谢!
  回复  引用  查看    
#12楼 [楼主]2006-08-16 08:59 | THIN      
@阿贵
string pattern = "<a href=\"personen\\.d4w([^<]|<(?!/tr>))*";
string test = "asdfasdf<a href=\"personen.d4w><b>asdfas</b>开头到第一个</tr>结束</tr>";

Regex reg = new Regex(pattern,RegexOptions.IgnoreCase);
Console.WriteLine(reg.Match(test).Value);
//输出:asdfasdf<a href="personen.d4w><b>asdfas</b>开头到第一个
  回复  引用  查看    
#13楼 2007-04-03 15:43 | 随风随云      
收获不小 例子短小生动 赞~~
  回复  引用    
#14楼 2007-04-13 18:25 | stone [未注册用户]
very good. thank you
  回复  引用    
#15楼 2007-09-11 11:12 | 由灵 [未注册用户]
太好了,老大的文章入木三分呀~!!
  回复  引用    
#16楼 2008-01-31 16:28 | 台州啦 [未注册用户]
看得晕晕的

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2006-03-03 09:38 编辑过
"五向定位"职业成长路线公开课(上海、南京、大连)
Google站内搜索


相关链接: