我对基本的reg-ex很满意。但是,这行代码用于使大量的千分离超出了我的知识和谷歌它相当多,也不能满足我的好奇心。你们谁能花点时间给我解释一下下面这行代码吗?
someString.replaceAll("(\\G-?\\d{1,3})(?=(?:\\d{3})++(?!\\d))", "$1,");我特别不理解正则表达式结构"(?=(?:\d{3})++(?!\d))"。
在此之前非常感谢。
发布于 2012-04-08 00:08:48
"(?=(?:\d{3})++(?!\d))"是一个lookahead assertion。
它的意思是“只有在((我们不需要捕获的三个数字)重复一次或多次(并再次重复一次或多次)(后面不跟数字)的情况下才匹配”。请参阅这个关于(?:...)表示法的explanation。它被称为非捕获组,这意味着你在比赛后不需要引用这个组。
"(\\G-?\\d{1,3})"是应该实际匹配的部分(但仅当满足上述条件时)。
编辑:我认为+必须是一个特殊的字符,否则它只是一个加号。如果它是一个特殊字符(快速搜索显示为it is in Java, too),则第二个字符是多余的。
编辑2:多亏了Alan Moore,它现在变得清晰了。第二个+意味着所有匹配,所以它意味着如果在检查了尽可能多的3位数组后,它不会发现它们后面没有非数字,引擎将立即放弃,而不是后退一个3位数组。
发布于 2012-04-08 00:21:36
这个表达式中包含了一些高级内容。首先,最简单的:\d{3}恰好是三位数。这是你的数千人。
然后:++是+的变体(这意味着一个或多个),但所有格,这意味着它将吃掉数千个。我不完全确定为什么这是必要的。
?:意味着它是一个非捕获组-我认为这只是出于性能原因,可以省略。
?=是一个积极的先行检查-我认为这意味着它只检查该组是否存在,而不会计入匹配的字符串-这意味着它不会被替换。
?!是一个负向先行-我不太理解这一点,但我认为它意味着它必须不匹配,这反过来意味着在匹配序列的末尾不能有另一个数字。这确保了第一组得到正确的数字。例如,10000只能作为10(000)匹配,而不是1(000)0,如果你明白我的意思。
通过lookaheads,如果我理解正确(我还没有测试它),只有第一组实际上会被替换,因为它是匹配的那一组。
发布于 2012-04-08 03:46:14
对我来说,这个正则表达式中最有趣的部分是\G。我花了一段时间才记起它的作用:防止在分数部分中添加逗号(如果有)。如果正则表达式只是:
(-?\d{1,3})(?=(?:\d{3})++(?!\d))...this编号:
12345.67890...would的结尾为:
12,345.67,890但是将\G添加到开头意味着匹配只能从字符串的开头或前一个匹配结束的位置开始。所以它不匹配345,因为它后面跟着.,它也不匹配67,因为它必须跳过一些字符串才能做到这一点。因此它正确地返回:
12,345.67890我知道这不是问题的答案,但我认为它值得一提。
https://stackoverflow.com/questions/10055885
复制相似问题