过节兼问问题!正则高手进! ((?<=\d)\d{3})*\b执行数据:7894561231234567890-123456执行结果:456123234567890456((?<=\d)\d{3})*\b 这条正则真没看懂!它执行流程是怎样的???详细解说! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 Capture Capture ? (zero or one time) ' ' (space)<= Any digit End CaptureAny digit Exactly 3 times数字后面,跟着3数字一组的任意数字字符 这个正则大概是这样的:前面有个数字((? <=\d)\d{3})*\b,这个数字不参与匹配(((? <=\d)\d{3})*\b),它的后面必须满足这个条件:(有三个数字(((? <=\d)\d{3})*\b),而且这三个数字要在文本的末尾(((? <=\d)\d{3})*\b),)括号中的是个子匹配,可以有多个而且是贪婪匹配(((? <=\d)\d{3})*\b))。匹配过程我自己感觉应该是这样的:首先应该满足这样的条件:在文本末尾,而且是3个数字(这个子匹配是个贪婪匹配,所以如果是多个(3个数字),就会匹配多个(3个数字),而不仅仅返回一个(3个数字))然后它前面要是个数字,而且这个数字不参与匹配。789456123 //先找到123,向前延伸到456,再向前延伸到789,前面没有数字,不匹配,返回上次匹配的结果456+1231234567890 //同理,找到234再向前延伸时,不匹配(没有三个数字了),返回234+567+890-123456 //找到456后,向前延伸找到123,前面不是数字,返回上一个匹配456============我自己理解的是这样。不知道对不对。 ((?<=\d)\d{3})*\b测试了一些数据公布一下:看看本人的分析是否正确!!4588865we8789返回789(?<=\d)返回一个数字之后的位置--也就是4的后面开始匹配d{3}---采用贪婪匹配--一直到865 指定\b后到we8789不满足匹配。**********************这个区域是推断,我也没有证据,贪婪匹配很有可能不执行*************第二次从5后开始贪婪匹配也是同样的结果。经过7次后到达we***************************************************************************************跳过(?<=\d)进入8的后面。就是倒数第二个8 采用贪婪匹配789满足--返回789 其实这个正则可以改成下面这个正则来进行理解:(?<=\d)(\d{3})*\b(\d{3})*是贪婪匹配,也就是匹配3的倍数个数字由于前面还有个(?<=\d),表示匹配值的前面还必须有一个数字,但这个数字只是作为条件,并不是匹配的Value 首先,这个正则只在极特殊的情况下才有意义,绝大多数情况下,它的意义只存在于理论上,如果换成((?<=\d)\d{3})+\b,才会有些实际意义其次,我不知道楼主是在哪里调试的,用的什么样的调试代码,执行结果怎么可能是楼主给出的结果 string[] test = new string[] { "789456123", "1234567890", "-123456" };foreach (string s in test){ richTextBox2.Text += "源字符串:" + s + "\n"; MatchCollection mc = Regex.Matches(s, @"((?<=\d)\d{3})*\b"); foreach (Match m in mc) { richTextBox2.Text += "匹配结果:" + m.Value + ",Index:" + m.Index + ",Length:" + m.Length + "\n"; } richTextBox2.Text += "\n";}//输出源字符串:789456123匹配结果:,Index:0,Length:0匹配结果:456123,Index:3,Length:6匹配结果:,Index:9,Length:0源字符串:1234567890匹配结果:,Index:0,Length:0匹配结果:234567890,Index:1,Length:9匹配结果:,Index:10,Length:0源字符串:-123456匹配结果:,Index:1,Length:0匹配结果:456,Index:4,Length:3匹配结果:,Index:7,Length:0之所以说楼主这个正则只有在极特殊情况下才有意义,是因为整个表达式可以匹配零宽度的字符串,所以在源字符串是任何形式的情况下,都会有匹配成功的结果,通常来说,这是没有意义的最后,来分析一下这个正则的匹配原理这个问题跟我前几天回答的另一个帖子,有很多相似之处,可以先参考一下这个帖子10楼主的归纳方法,正则表达式正向预搜索的问题楼主的表达式,也可以进行归纳,最终就可以归纳为((? <=\d)(\d{3})*)?\b当然,这个表达式似乎也不是那么容易理解,所以还是按原来的表达式分析吧之所以不能写成(?<=\d)(\d{3})*\b,是因为(?<=\d)并不是必须的,只有后面出现\d{3}时,它才是必须的我只分析一个源字符串是789456123的情况,其它源字符串原理一样源字符串:789456123正则表达式:((?<=\d)\d{3})*\b首先对源字符串进行一下说明,字符“7”之前,是字符串的起始位置,记作位置0,字符“7”和字符“8”之间记作位置1,以此类推首先从位置0开始尝试匹配,正则引擎把控制权交给((?<=\d)\d{3})*,可以把它看作(Exp)*,因为是贪婪模式,正则引擎会先尝试用Exp来进行匹配,此时控制权交给(?<=\d),在位置0处,它的左侧没有任何字符,当然也就不会是数字,所以在位置0处,(?<=\d)匹配失败,(?<=\d)\d{3}也就匹配失败,回溯,((?<=\d)\d{3})*不进行匹配,此时控制权交给\b,位置0左侧和右侧满足\b条件,\b在位置0匹配成功,整个表达式在位置0处就匹配成功,因些会返回匹配结果,匹配内容为空字符串,Index为0,长度当然就是0继续尝试下一次匹配,此时正则引擎会引导正则向前传动,从上一次匹配成功的结束位置开始尝试匹配,如果匹配成功的开始和结束位置相同,则从下一个位置开始尝试匹配接下来也就是在位置1尝试匹配,正则引擎把控制权交给((?<=\d)\d{3})*,因为位置1的左侧是字符“7”,满足要求,向右匹配三个数字,先是“8”,接着“9”,接着“4”,匹配成功,这时((?<=\d)\d{3})*会接着上次匹配成功的位置,尝试第二次匹配,同样成功的匹配了“561”,接着尝试第三次匹配,首先匹配成功了“2”,接着匹配成功了“3”,再向右匹配,因为不是数字,匹配失败,((?<=\d)\d{3})*回溯,((?<=\d)\d{3})成功匹配了两次,也就是匹配成功了“894561”,正则引擎把控制权交给\b,在“1”后面,“2”前面这个位置尝试匹配,当然匹配失败,((?<=\d)\d{3})*再回溯,匹配成功一次,也就是匹配成功了“894”,正则引擎把控制权交给\b,在“4”后面,“5”前面这个位置尝试匹配,当然匹配失败,((?<=\d)\d{3})*再回溯,匹配成功零次,也就是不匹配,正则引擎把控制权交给\b,在“7”后面,“8”前面这个位置尝试匹配,当然匹配失败,((?<=\d)\d{3})*已经无法再回溯,此时整个表达式匹配失败继续尝试下一次匹配,此时正则引擎会引导正则向前传动,从下一个位置开始尝试匹配,也就是在位置2尝试匹配,过程同上,同样匹配失败继续尝试下一次匹配,此时正则引擎会引导正则向前传动,从下一个位置开始尝试匹配,也就是在位置3尝试匹配,过程同上,((?<=\d)\d{3})*成功匹配两次,此时在结束位置,\b也匹配成功,因此整个表达式匹配成功,匹配内容为“456123”,Index为3,长度为6继续尝试下一次匹配,此时正则引擎会引导正则向前传动,从下一个位置开始尝试匹配,也就是在结束位置尝试匹配,过程同上,((?<=\d)\d{3})*匹配零次,\b匹配成功,整个表达式匹配成功,匹配内容为空字符串,Index为9,长度当然就是0 另外要说明一点,在.NET等使用Unicode的语言和javascript等使用ASCII码的语言中,\b的意义虽然可以采用同样的解释,但是匹配的结果是不一样的源字符串:a中文正则表达式:a\b在.NET中是匹配失败的,而在javascript中是匹配成功的.NET中,只有加了RegexOptions.ECMAScript参数,\b的意义才与javascript中一样 "(?<=\d{4})\d+(?=\d{4})" 返回前四个和后四个数字之间的数据。(?<=\d{4})应该是返回右侧位置,((? <=\d),在位置0处,它的左侧没有任何字符,当然也就不会是数字,老大所说)到底是右侧还是左侧啊???本人这有个NET2.0(安装NET)的正则验证工具---谁需要留下邮箱!!! (?<=Exp)和(?<!Exp)是负向预搜索,是对所在位置左侧附加的判定条件(?=Exp)和(?!Exp)是正向预搜索,是对所在位置右侧附加的判定条件以上四个表达式都是零宽度的,只对所在位置左或右进行规则判定,匹配内容并不计入最后的匹配结果 正则名词并不多,只不过正则流派太多,没有一个统一的标准,各种语言实现起来就各有各的特点.NET目前是正则实现最完备,功能最大强的语言,这是不可否认的同样不可否认的一点,就是MSDN中关于正则部分的文档却与它的程序相反,做得那是相当的烂,然后再翻译成中文,那几乎就是惨不忍睹,所以到目前为止,我还没有把MSDN中关于正则的部分看全过,像什么“零宽度正回顾后发断言”,简直就像绕口令不过知道所谓的“零宽度正回顾后发断言”,“负向预搜索”,“逆序环视”等等指的都是一种语法,使用熟练了,叫什么也就无所谓了 关于petshop安装的问题----请指教 ASP.net 在连接中加入变量???急银屏急 关于“?:” detailsview 中字段值的获取和设置的问题 关于日期查询,谢谢 在线编辑器的输入框是什么控件呢?插入表情就可以显示在里面,怎么弄的呢? 求教:汉字列如何运用 大哥大姐们快来救急啊,这个怎么实现啊(关于页面的动态效果),如果分不够,可以再加!我急啊! 网站发布到服务器后,程序一出错,网站就崩了 图片显示的问题(很弱智),问题解决马上给分 急,急!将数据库链接代码做成组件类! 事务的问题,胸闷了一下午了,求大侠们指点
Capture
? (zero or one time)
' ' (space)<=
Any digit
End Capture
Any digit
Exactly 3 times数字后面,跟着3数字一组的任意数字字符
前面有个数字((? <=\d)\d{3})*\b,这个数字不参与匹配(((? <=\d)\d{3})*\b),它的后面必须满足这个条件:(有三个数字(((? <=\d)\d{3})*\b),而且这三个数字要在文本的末尾(((? <=\d)\d{3})*\b),)括号中的是个子匹配,可以有多个而且是贪婪匹配(((? <=\d)\d{3})*\b))。
匹配过程我自己感觉应该是这样的:
首先应该满足这样的条件:在文本末尾,而且是3个数字(这个子匹配是个贪婪匹配,所以如果是多个(3个数字),就会匹配多个(3个数字),而不仅仅返回一个(3个数字))
然后它前面要是个数字,而且这个数字不参与匹配。
789456123 //先找到123,向前延伸到456,再向前延伸到789,前面没有数字,不匹配,返回上次匹配的结果456+123
1234567890 //同理,找到234再向前延伸时,不匹配(没有三个数字了),返回234+567+890
-123456 //找到456后,向前延伸找到123,前面不是数字,返回上一个匹配456
============
我自己理解的是这样。不知道对不对。
返回789
(?<=\d)返回一个数字之后的位置--也就是4的后面
开始匹配d{3}---采用贪婪匹配--一直到865 指定\b后到we8789不满足匹配。**********************这个区域是推断,我也没有证据,贪婪匹配很有可能不执行*************
第二次从5后开始贪婪匹配也是同样的结果。经过7次后到达we
***************************************************************************************
跳过(?<=\d)进入8的后面。就是倒数第二个8 采用贪婪匹配789满足--返回789
(?<=\d)(\d{3})*\b
(\d{3})*是贪婪匹配,也就是匹配3的倍数个数字
由于前面还有个(?<=\d),表示匹配值的前面还必须有一个数字,但这个数字只是作为条件,并不是匹配的Value
首先,这个正则只在极特殊的情况下才有意义,绝大多数情况下,它的意义只存在于理论上,如果换成((?<=\d)\d{3})+\b,才会有些实际意义其次,我不知道楼主是在哪里调试的,用的什么样的调试代码,执行结果怎么可能是楼主给出的结果
string[] test = new string[] { "789456123", "1234567890", "-123456" };
foreach (string s in test)
{
richTextBox2.Text += "源字符串:" + s + "\n";
MatchCollection mc = Regex.Matches(s, @"((?<=\d)\d{3})*\b");
foreach (Match m in mc)
{
richTextBox2.Text += "匹配结果:" + m.Value + ",Index:" + m.Index + ",Length:" + m.Length + "\n";
}
richTextBox2.Text += "\n";
}
//输出
源字符串:789456123
匹配结果:,Index:0,Length:0
匹配结果:456123,Index:3,Length:6
匹配结果:,Index:9,Length:0源字符串:1234567890
匹配结果:,Index:0,Length:0
匹配结果:234567890,Index:1,Length:9
匹配结果:,Index:10,Length:0源字符串:-123456
匹配结果:,Index:1,Length:0
匹配结果:456,Index:4,Length:3
匹配结果:,Index:7,Length:0之所以说楼主这个正则只有在极特殊情况下才有意义,是因为整个表达式可以匹配零宽度的字符串,所以在源字符串是任何形式的情况下,都会有匹配成功的结果,通常来说,这是没有意义的最后,来分析一下这个正则的匹配原理
这个问题跟我前几天回答的另一个帖子,有很多相似之处,可以先参考一下这个帖子10楼主的归纳方法,正则表达式正向预搜索的问题楼主的表达式,也可以进行归纳,最终就可以归纳为
((? <=\d)(\d{3})*)?\b
当然,这个表达式似乎也不是那么容易理解,所以还是按原来的表达式分析吧
之所以不能写成(?<=\d)(\d{3})*\b,是因为(?<=\d)并不是必须的,只有后面出现\d{3}时,它才是必须的我只分析一个源字符串是789456123的情况,其它源字符串原理一样
源字符串:789456123
正则表达式:((?<=\d)\d{3})*\b首先对源字符串进行一下说明,字符“7”之前,是字符串的起始位置,记作位置0,字符“7”和字符“8”之间记作位置1,以此类推首先从位置0开始尝试匹配,正则引擎把控制权交给((?<=\d)\d{3})*,可以把它看作(Exp)*,因为是贪婪模式,正则引擎会先尝试用Exp来进行匹配,此时控制权交给(?<=\d),在位置0处,它的左侧没有任何字符,当然也就不会是数字,所以在位置0处,(?<=\d)匹配失败,(?<=\d)\d{3}也就匹配失败,回溯,((?<=\d)\d{3})*不进行匹配,此时控制权交给\b,位置0左侧和右侧满足\b条件,\b在位置0匹配成功,整个表达式在位置0处就匹配成功,因些会返回匹配结果,匹配内容为空字符串,Index为0,长度当然就是0继续尝试下一次匹配,此时正则引擎会引导正则向前传动,从上一次匹配成功的结束位置开始尝试匹配,如果匹配成功的开始和结束位置相同,则从下一个位置开始尝试匹配接下来也就是在位置1尝试匹配,正则引擎把控制权交给((?<=\d)\d{3})*,因为位置1的左侧是字符“7”,满足要求,向右匹配三个数字,先是“8”,接着“9”,接着“4”,匹配成功,这时((?<=\d)\d{3})*会接着上次匹配成功的位置,尝试第二次匹配,同样成功的匹配了“561”,接着尝试第三次匹配,首先匹配成功了“2”,接着匹配成功了“3”,再向右匹配,因为不是数字,匹配失败,((?<=\d)\d{3})*回溯,((?<=\d)\d{3})成功匹配了两次,也就是匹配成功了“894561”,正则引擎把控制权交给\b,在“1”后面,“2”前面这个位置尝试匹配,当然匹配失败,((?<=\d)\d{3})*再回溯,匹配成功一次,也就是匹配成功了“894”,正则引擎把控制权交给\b,在“4”后面,“5”前面这个位置尝试匹配,当然匹配失败,((?<=\d)\d{3})*再回溯,匹配成功零次,也就是不匹配,正则引擎把控制权交给\b,在“7”后面,“8”前面这个位置尝试匹配,当然匹配失败,((?<=\d)\d{3})*已经无法再回溯,此时整个表达式匹配失败继续尝试下一次匹配,此时正则引擎会引导正则向前传动,从下一个位置开始尝试匹配,也就是在位置2尝试匹配,过程同上,同样匹配失败继续尝试下一次匹配,此时正则引擎会引导正则向前传动,从下一个位置开始尝试匹配,也就是在位置3尝试匹配,过程同上,((?<=\d)\d{3})*成功匹配两次,此时在结束位置,\b也匹配成功,因此整个表达式匹配成功,匹配内容为“456123”,Index为3,长度为6继续尝试下一次匹配,此时正则引擎会引导正则向前传动,从下一个位置开始尝试匹配,也就是在结束位置尝试匹配,过程同上,((?<=\d)\d{3})*匹配零次,\b匹配成功,整个表达式匹配成功,匹配内容为空字符串,Index为9,长度当然就是0
正则表达式:a\b在.NET中是匹配失败的,而在javascript中是匹配成功的
.NET中,只有加了RegexOptions.ECMAScript参数,\b的意义才与javascript中一样
"(?<=\d{4})\d+(?=\d{4})" 返回前四个和后四个数字之间的数据。
(?<=\d{4})应该是返回右侧位置,((? <=\d),在位置0处,它的左侧没有任何字符,当然也就不会是数字,老大所说)到底是右侧还是左侧啊???本人这有个NET2.0(安装NET)的正则验证工具---谁需要留下邮箱!!!
(?<=Exp)和(?<!Exp)是负向预搜索,是对所在位置左侧附加的判定条件
(?=Exp)和(?!Exp)是正向预搜索,是对所在位置右侧附加的判定条件以上四个表达式都是零宽度的,只对所在位置左或右进行规则判定,匹配内容并不计入最后的匹配结果
.NET目前是正则实现最完备,功能最大强的语言,这是不可否认的
同样不可否认的一点,就是MSDN中关于正则部分的文档却与它的程序相反,做得那是相当的烂,然后再翻译成中文,那几乎就是惨不忍睹,所以到目前为止,我还没有把MSDN中关于正则的部分看全过,像什么“零宽度正回顾后发断言”,简直就像绕口令不过知道所谓的“零宽度正回顾后发断言”,“负向预搜索”,“逆序环视”等等指的都是一种语法,使用熟练了,叫什么也就无所谓了