下面我所写的都是参考自精通正则表达式(第三版).
什么是环视
环视顾名思义就是从四周看。正则表达式一向都是从左向右工作的,但是环视也能从右向左工作。最典型的列子就是给你一个数字如
12345678,需要你改成12,345,678这种格式。如果按照我们的思维来,应该是会从右边开始划分吧,每三个数字加一个逗号。环视就能按照我们的思维去解决这样的问题。这里要注意的是环视不匹配任何字符,只是匹配位置而已。作用和^,&相似。环视又分为顺序环视和逆序环视。也就是从左到右工作和从右到左的区别.顺序环视在正则中用(?=)表示,包含括号。逆序用(?<=)
我们来举个简单的列子来解释顺序和逆序环视的作用。比如给定一个字符串”hellowld”我们想在”ld”前面插入一个”or”字符。下面是简单的java实现。
String strTest = "hellowld"; Pattern pattern = Pattern.compile("(?=ld)"); Matcher matcher = pattern.matcher(strTest); System.out.printf(matcher.replaceAll("or"));
这段代码中真正匹配到的字符串是”ld”,所谓的顺序环视就是在匹配这个字符串前的那个位置。
相信大家现在应该能够推测出逆序环视了吧。匹配的是ld后面那个位置。
环视的例子
理解了上诉环视的列子我们来解决一开始那个问题。我们可以先分析一下,需要满足这样的条件。左边要是数字,右边的数字个数是3的倍数。
接下来就是对这个条件所实现的java代码。
String str = "12345678"; Pattern pattern = Pattern.compile("(?<=\\d)(?=(\\d{3})+$)"); Matcher matcher = pattern.matcher(str); System.out.printf(matcher.replaceAll(","));(?<=\\d)这个表达式满足了左边是数字,可以想象一下。因为逆序环视是匹配字符串右边的位置,也就是\d右边的位置。那不就是说明了这个位置的左边是\d吗。对(?=(\\d{3})+$)的理解可能有点不太容易。如果是孤立的(\\d{3})+$匹配的是从字符串末尾向左数字的个数正好是3的倍数。但是加入顺序环视之后意义就不一样了它能匹配右边数字的个数正好是3的倍数的位置。$是关键,没有了这个符号,也就意味着可以不是从最后一个数字开始匹配的。这里可以结合程序好好的想想。这样两个条件就都满足了。也就能够匹配到正确的位置了。
但是如果给的字符串不一定是纯数字,可能是”12345678$”这样的形式,上诉的正则就不管用了。在这里我再引入两个概念就是否定顺序环视(?!)和否定逆序环视(?<!)。
在(?=表达式)中,意味表达式能够匹配右侧的文本,而(?!表达式)则以为表达式不能匹配右侧的文本。那么可以将正则改成
"(?<=\\d)(?=(\\d{3})+(?!\\d))"也许你认为可以将(?!\\d)改成\D,但是这两个其实是有区别的,\D是匹配一个非数字的字符,也就是说必须匹配一个字符。如果给你的数字是"12345678"这样就不能得到匹配了.