((?<=\d)\d{3})*\b执行数据:
789456123
1234567890
-123456
执行结果:
456123
234567890
456
((?<=\d)\d{3})*\b 这条正则真没看懂!它执行流程是怎样的???详细解说!

解决方案 »

  1.   

    Capture
      Capture
      ? (zero or one time)
      ' ' (space)<=
      Any digit 
    End Capture
    Any digit 
    Exactly 3 times数字后面,跟着3数字一组的任意数字字符
      

  2.   

    这个正则大概是这样的:
    前面有个数字((? <=\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
    ============
    我自己理解的是这样。不知道对不对。
      

  3.   

    ((?<=\d)\d{3})*\b测试了一些数据公布一下:看看本人的分析是否正确!!4588865we8789
    返回789
    (?<=\d)返回一个数字之后的位置--也就是4的后面
    开始匹配d{3}---采用贪婪匹配--一直到865  指定\b后到we8789不满足匹配。**********************这个区域是推断,我也没有证据,贪婪匹配很有可能不执行*************
    第二次从5后开始贪婪匹配也是同样的结果。经过7次后到达we
    ***************************************************************************************
    跳过(?<=\d)进入8的后面。就是倒数第二个8 采用贪婪匹配789满足--返回789
      

  4.   

    其实这个正则可以改成下面这个正则来进行理解:
    (?<=\d)(\d{3})*\b
    (\d{3})*是贪婪匹配,也就是匹配3的倍数个数字
    由于前面还有个(?<=\d),表示匹配值的前面还必须有一个数字,但这个数字只是作为条件,并不是匹配的Value
      

  5.   


    首先,这个正则只在极特殊的情况下才有意义,绝大多数情况下,它的意义只存在于理论上,如果换成((?<=\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
      

  6.   

    另外要说明一点,在.NET等使用Unicode的语言和javascript等使用ASCII码的语言中,\b的意义虽然可以采用同样的解释,但是匹配的结果是不一样的源字符串:a中文
    正则表达式:a\b在.NET中是匹配失败的,而在javascript中是匹配成功的
    .NET中,只有加了RegexOptions.ECMAScript参数,\b的意义才与javascript中一样
      

  7.   


     "(?<=\d{4})\d+(?=\d{4})"  返回前四个和后四个数字之间的数据。
    (?<=\d{4})应该是返回右侧位置,((? <=\d),在位置0处,它的左侧没有任何字符,当然也就不会是数字,老大所说)到底是右侧还是左侧啊???本人这有个NET2.0(安装NET)的正则验证工具---谁需要留下邮箱!!!
      

  8.   


    (?<=Exp)和(?<!Exp)是负向预搜索,是对所在位置左侧附加的判定条件
    (?=Exp)和(?!Exp)是正向预搜索,是对所在位置右侧附加的判定条件以上四个表达式都是零宽度的,只对所在位置左或右进行规则判定,匹配内容并不计入最后的匹配结果
      

  9.   

    正则名词并不多,只不过正则流派太多,没有一个统一的标准,各种语言实现起来就各有各的特点
    .NET目前是正则实现最完备,功能最大强的语言,这是不可否认的
    同样不可否认的一点,就是MSDN中关于正则部分的文档却与它的程序相反,做得那是相当的烂,然后再翻译成中文,那几乎就是惨不忍睹,所以到目前为止,我还没有把MSDN中关于正则的部分看全过,像什么“零宽度正回顾后发断言”,简直就像绕口令不过知道所谓的“零宽度正回顾后发断言”,“负向预搜索”,“逆序环视”等等指的都是一种语法,使用熟练了,叫什么也就无所谓了