在Groovy中编写正则表达式

与Java相比, 在Groovy中编写正则表达式(regexes)简直是一种乐趣。在 Java中, regexes编程不仅需处理Pattern和Matcher对象,而且还要编写繁琐的 样板代码(boilerplate coding)。而Groovy对这两个Java对象做了简单封装, 添加了一些额外的实用方法,并给出一个简化的新的语法和3个新的操作符。

Groovy中,您可用slashy(斜线)语法“/../”定义字符串。这样以来便可避 免在Java正则表达式中使用过多的反斜线。例如:

assert (/Hello World/ in String)<br />assert (/Hi /there/ == 'Hi //there')

Groovy新增的第1个正则表达式操作符便是模式操作符(~),它使得字符串被 编译成一个Pattern实例。例如:

p = ~//b[a-zA-Z]/b/

也可使用Java实现,如:

import java.util.regex.*<br />Pattern p = Pattern.compile("//b[a-zA-Z]//b");

表3.1中列出了常用的正则表达式模式及含义。完整的正则表达式清单可参考 Pattern API文档, http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html。

表3.1 常用的正则表达式模式

模式 含义

a?

尽可能匹配1次a,也可以不匹配

a*

表达式尽可能的多匹配a,最少可以不匹配

a+

尽可能的多匹配a,至少匹配1次

a|b

匹配a或b

(ab)

分组

.

匹配任意一个字符

[abc]

匹配a,b或c

[^abc]

匹配除了a,b或c的任意一个字符

[a-z]

匹配a到z之间的任意一个字母

/d

任意一个数字,0-9 中的任意一个

/s

空格、制表符、换页符等空白字符的其中任意一个

/w

任意一个字母或数字或下划线,也就是 A-Z,a-z,0-9,_ 中任意一个

/b

匹配一个单词边界,也就是单词和空格之间的位置,不匹配任何字符

^

与字符串开始的地方匹配,不匹配任何字符

$

与字符串结束的地方匹配,不匹配任何字符

第2个操作符是查找操作符(=~),它负责从左边的字符串和右边的模式来创 建一个Matcher对象。

import java.util.regex.Matcher<br />def matcher = "Groovy" =~ /G.*/<br />assert matcher in Matcher<br />assert matcher.matches()

同理,其Java实现,如:

import java.util.regex.*;<br />Pattern pattern = Pattern.compile("G.*");<br />Matcher matcher = pattern.matcher("Groovy");<br />matcher.matches();

您可把Matcher对象看作一个二维矩阵。第1维表示每一个与模式相匹配的字符 串;第2维表示每个匹配内的捕获组(capture group),详见清单3.2中的例子。

清单3.2 Using Regexes Groups with Matcher

def text = """<br />Lorem 1:30 PM ipsum dolor 12:00 PM sit amet, consectetuer adipiscing elit.<br />def HOUR = /10|11|12|[0-9]/<br />def MINUTE = /[0-5][0-9]/<br />def AM_PM = /AM|PM/<br />def time = /($HOUR):($MINUTE) ($AM_PM)/<br />def matcher = text =~ time<br />assert matcher[0] == ["1:30 PM", "1", "30", "PM"] //First Match<br />assert matcher[0][0] == "1:30 PM" //First match group in the first match<br />assert matcher[0][1] == "1" //Second match group in the first match (HOUR)<br />assert matcher[0][2] == "30" //Third match group in the first match (MINUTE)<br />assert matcher[0][3] == "PM" //Fourth match group in the first match (AM_PM)<br />assert matcher[1] == ["12:00 PM", "12", "00", "PM"] //Second Match<br />assert matcher[1][0] == "12:00 PM" //First match group in the second match<br />assert matcher[1][1] == "12" //Second match group in the second match (HOUR)<br />assert matcher[1][2] == "00" //Third match group in the second match (MINUTE)<br />assert matcher[1][3] == "PM" //Fourth match group in the second match (AM_PM)

最后一个是匹配操作符(==~),该操作符返回一个Boolean值,说明操作符左 侧的整个字符串是否右侧的模式相匹配,例如:

assert "Groovy" ==~ /G.*/<br />assert 123 ==~ //d+/<br />assert !123 ==~ //D+/

正则表达式也可与String的replace*形式的方法(如replaceFirst等)结合使 用。例如:

//把第一次出现的数字替换为“To”<br />assert "Welcome To Groovy" == "Welcome 2 Groovy".replaceFirst(//d/, "To")

GDK String还提供了一个可接受闭包的replace方法,该闭包可用来操作每个 捕捉组(captured group),例如

//把所有的“Groovy”转换为大写形式<br />"Hello GROOVY, GROOVY rocks" == "Hello Groovy, Groovy rocks"<br />.replaceAll("Groovy") {Object[] it ->it[0].toUpperCase()}

您可以使用grep方法,该方法利用正则表达式筛选一个集合,并返回集合中满 足给定过滤条件的元素。例如:

//返回集合中以“G”开头的元素<br />assert ["Groovy"] == ["Groovy","Rocks"].grep(~/G.*/)

无做什么,记得为自己而做,那就毫无怨言。

在Groovy中编写正则表达式

相关文章:

你感兴趣的文章:

标签云: