在Groovy中編寫正則表達(dá)式
與Java相比, 在Groovy中編寫正則表達(dá)式(regexes)簡直是一種樂趣。在Java中, regexes編程不僅需處理Pattern和Matcher對(duì)象,而且還要編寫繁瑣的樣板代碼(boilerplate coding)。而Groovy對(duì)這兩個(gè)Java對(duì)象做了簡單封裝,添加了一些額外的實(shí)用方法,并給出一個(gè)簡化的新的語法和3個(gè)新的操作符。
Groovy中,您可用slashy(斜線)語法“/../”定義字符串。這樣以來便可避免在Java正則表達(dá)式中使用過多的反斜線。例如:
- assert (/Hello World/ in String)
- assert (/Hi \there/ == 'Hi \\there')
Groovy新增的第1個(gè)正則表達(dá)式操作符便是模式操作符(~),它使得字符串被編譯成一個(gè)Pattern實(shí)例。例如:
- p = ~/\b[a-zA-Z]\b/
也可使用Java實(shí)現(xiàn),如:
- import java.util.regex.*
- Pattern p = Pattern.compile("\\b[a-zA-Z]\\b");
表3.1中列出了常用的正則表達(dá)式模式及含義。完整的正則表達(dá)式清單可參考Pattern API文檔,http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html。
表3.1 常用的正則表達(dá)式模式
模式 含義
a?
盡可能匹配1次a,也可以不匹配
a*
表達(dá)式盡可能的多匹配a,最少可以不匹配
a+
盡可能的多匹配a,至少匹配1次
a|b
匹配a或b
(ab)
分組
.
匹配任意一個(gè)字符
[abc]
匹配a,b或c
[^abc]
匹配除了a,b或c的任意一個(gè)字符
[a-z]
匹配a到z之間的任意一個(gè)字母
\d
任意一個(gè)數(shù)字,0-9 中的任意一個(gè)
\s
空格、制表符、換頁符等空白字符的其中任意一個(gè)
\w
任意一個(gè)字母或數(shù)字或下劃線,也就是 A-Z,a-z,0-9,_ 中任意一個(gè)
\b
匹配一個(gè)單詞邊界,也就是單詞和空格之間的位置,不匹配任何字符
^
與字符串開始的地方匹配,不匹配任何字符
$
與字符串結(jié)束的地方匹配,不匹配任何字符
第2個(gè)操作符是查找操作符(=~),它負(fù)責(zé)從左邊的字符串和右邊的模式來創(chuàng)建一個(gè)Matcher對(duì)象。
- import java.util.regex.Matcher
- def matcher = "Groovy" =~ /G.*/
- assert matcher in Matcher
- assert matcher.matches()
同理,其Java實(shí)現(xiàn),如:
- import java.util.regex.*;
- Pattern pattern = Pattern.compile("G.*");
- Matcher matcher = pattern.matcher("Groovy");
- matcher.matches();
您可把Matcher對(duì)象看作一個(gè)二維矩陣。第1維表示每一個(gè)與模式相匹配的字符串;第2維表示每個(gè)匹配內(nèi)的捕獲組(capture group),詳見清單3.2中的例子。
清單3.2 Using Regexes Groups with Matcher
- def text = """
- Lorem 1:30 PM ipsum dolor 12:00 PM sit amet, consectetuer adipiscing elit.
- """
- def HOUR = /10|11|12|[0-9]/
- def MINUTE = /[0-5][0-9]/
- def AM_PM = /AM|PM/
- def time = /($HOUR):($MINUTE) ($AM_PM)/
- def matcher = text =~ time
- assert matcher[0] == ["1:30 PM", "1", "30", "PM"] //First Match
- assert matcher[0][0] == "1:30 PM" //First match group in the first match
- assert matcher[0][1] == "1" //Second match group in the first match (HOUR)
- assert matcher[0][2] == "30" //Third match group in the first match (MINUTE)
- assert matcher[0][3] == "PM" //Fourth match group in the first match (AM_PM)
- assert matcher[1] == ["12:00 PM", "12", "00", "PM"] //Second Match
- assert matcher[1][0] == "12:00 PM" //First match group in the second match
- assert matcher[1][1] == "12" //Second match group in the second match (HOUR)
- assert matcher[1][2] == "00" //Third match group in the second match (MINUTE)
- assert matcher[1][3] == "PM" //Fourth match group in the second match (AM_PM)
***一個(gè)是匹配操作符(==~),該操作符返回一個(gè)Boolean值,說明操作符左側(cè)的整個(gè)字符串是否右側(cè)的模式相匹配,例如:
- assert "Groovy" ==~ /G.*/
- assert 123 ==~ /\d+/
- assert !123 ==~ /\D+/
正則表達(dá)式也可與String的replace*形式的方法(如replaceFirst等)結(jié)合使用。例如:
- //把***次出現(xiàn)的數(shù)字替換為“To”
- assert "Welcome To Groovy" == "Welcome 2 Groovy".replaceFirst(/\d/, "To")
GDK String還提供了一個(gè)可接受閉包的replace方法,該閉包可用來操作每個(gè)捕捉組(captured group),例如
- //把所有的“Groovy”轉(zhuǎn)換為大寫形式
- "Hello GROOVY, GROOVY rocks" == "Hello Groovy, Groovy rocks"
- .replaceAll("Groovy") {Object[] it ->it[0].toUpperCase()}
您可以使用grep方法,該方法利用正則表達(dá)式篩選一個(gè)集合,并返回集合中滿足給定過濾條件的元素。例如:
- //返回集合中以“G”開頭的元素
- assert ["Groovy"] == ["Groovy","Rocks"].grep(~/G.*/)
【編輯推薦】