日期:2014-05-20  浏览次数:20787 次

【C#】容易而又不简单的正则表达式,高手请进!
用正则表达式".*?"来匹配文本"abc",能正确匹配几次?分别匹配成功的是什么?请给出解释?

代码如下,大家可以试试,我希望得到的是理论上的答案。
C# code

string text = @"abc";
Regex r = new Regex(@".*?");
Console.WriteLine("r match count:" + r.Matches(text).Count);




------解决方案--------------------
.*?

.表示内容,没有用单行模式,所以.不能匹配回车换行。
*?表示非贪婪模式匹配,尽可能少的匹配以满足表达式成立,*表示0~n次,最少当然是0次。
a,b,c任意一个匹配到,.匹配次数都不是最少,所以,.*?匹配到4个位置,分别是a,b,c前面的位置和c后面的位置。
用*表示匹配为
*a*b*c*

我只是猜测,不确定解释的对不对。你的问题很不错,引申一下。
假设我上面说的是对的,那么.不能匹配的就是.*?表达式匹配的结果。
abc
def
匹配结果表示为*为:
*a*b*c*
*
*d*e*f*
这个好理解,因为非单行模式,.不能匹配换行回车。所以每个可见字符的前后和回车换行都成了.无法匹配的内容,反而成为了表达式.*?匹配的结果。

那么是不是(?s).*?呢?结果也是一样,只是匹配的位置是\r,\n之前的位置。用*占位表示依然是:
*a*b*c*
*
*d*e*f*
------解决方案--------------------
js和.net对待位置的区别就在这里体现出来了

下面是我对js实现的理解。如果有不对的地方,还请指正
假设
js中匹配位置不捕获。下面的字符中_表示位置
那么匹配_a_b_c_的过程是这样的
_成功,返回位置0,由于不捕获这个0位置,那么下一次匹配就是还是0位置。以至于出现了这样的死循环。
但是js的实现是捕获和记忆位置的
所以应该是把位置当作一个虚拟来对待。就是说位置0里面会有无数个空,而每次exec的时候都捕获了一个位置的空替代。

与之对应的。.net的应该是把位置当作一个虚拟字符(逍遥的解释)。则每次匹配了这个位置之后,即使没有匹配字符,下一次匹配的时候应该是把位置滑动到下一个位置。这样就导致了楼主的问题有4个匹配结果,而非死循环

js的伪代码如下
match = reg.exec(str);
alert(match.position) //output 0
reg.nextMatch()
alert(match.position)//output 0
...