Groovy 模式实战

现在已经准备好了用正则表达式做想要做的事情了,String有一个名称为eachMatch的方法,这个方法使用一个规则和一个闭包作为参数,闭包用来定义每一个符合规则的结果需要做的工作。

顺便说一下:匹配不是一个简单的字符串,而是一个字符串列表,在位置0包含了整个匹配,如果模式包括分组,那么可以通过match[n]进行访问,n是分组号,分组的编号通过它们在圆括号中的顺序决定的。

匹配结果将传递给闭包,在列表3.6中,把匹配的结果附加到结果字符串上。

这里有两种不同的途径用来遍历匹配的结果:如(1)使用String.eachMatch(Pattern),如(2)使用Matcher.each(),Matcher是应用规则到字符串和模式所得到的结果,(3)显示了通过闭包替换规则匹配的每一个结果,变量it引用匹配的子字符串,使用下划线替换“ain”。

为了完全理解Groovy是如何支持正则表达式的的,需要查看java.util.regex.Matcher类,这个JDK类包装了如下知识:

 什么位置和匹配的结果是什么

 为每一个匹配进行分组GDK按数组访问的方式增强了Matcher类,这是下面的例子(非常熟悉)匹配所有的非空白字符的结果:matcher = 'a b c' =~ /\S/ assert matcher[0] == 'a' assert matcher[1..2] == 'bc' assert matcher.count == 3在匹配结果中的分组是有趣的,如果模式定义分组时包含圆括号,mattcher返回的不是为每一个匹配结果返回一个单字符串,而是返回一个数组,完整的匹配是索引为0并且接下来的是分组信息,考虑这个例子,每一个匹配的结果是通过冒号分割的字符串对,为了后面的处理,匹配结果将冒号左边的字符串和右边的字符串分隔在两个组:matcher = 'a:1 b:2 c:3' =~ /(\S+):(\S+)/ assert matcher.hasGroup() assert matcher[0] == ['a:1', 'a', '1'] 换句话说,matcher[0]的返回结果依赖与模式是否进行了分组。

这也可以应用到matcher的each方法,每一个组都十分方便,在处理的闭包定义多个参数,参数按照分组列表进行定义:('xy' =~ /(.)(.)/).each { all, x, y -> assert all == 'xy' assert x == 'x' assert y == 'y' } 仅仅匹配了一次,但是包括了两个组,每一个组一个字符。

注意:groovy内部保存了最近使用的matcher(每线程),可以通过静态方法 Matcher.getLastMatcher来获取,也可以设置mathcer的index属性,使它可以通过 matcher.index=x来查看各自的匹配结果,这两者在特定的情况下都是有用的,参考 Matcher的API来了解更详细的信息。

在java和groovy中Matcher和Pattern结合在一起工作是关键概念,读者已经看到 了Matcher,在下一节我们将看到Pattern。