| Excerpt | ||
|---|---|---|
| ||
Groovy supports regular expressions natively using the ~"pattern" expression, which creates a compiled Java Pattern object from the given pattern string. Groovy also supports the =~ (create Matcher) and ==~ (returns boolean, whether String matches the pattern) operators. For matchers having groups, matcher[index] is either a matched String or a List of matched group Strings. |
Groovyはネイティブで ~"パターン" 表記を使用した正規表現をサポートします。それは、与えられたパターン文字列からコンパイルされた Java Pattern オブジェクトを生成します。また、Groovyは =~ 演算子(Matcherを生成)と ==~ 演算子(Stringとそのパターンがマッチするかどうかのboolean値を返す)もサポートします。
Matcherオブジェクトはグループを持つことがあるため、matcher[index]がマッチした文字列もしくはマッチしたグループの文字列リストとなります。
| Code Block |
|---|
import java.util.regex.Matcher
import java.util.regex.Pattern
// ~ はStringからPatternを生成します。
def pattern = ~/foo/
assert pattern instanceof Pattern
assert pattern.matcher("foo").matches() // TRUEを返します。
assert pattern.matcher("foobar").matches() // FALSEを返します。matches()はString全体にマッチしなければならないためです。
// =~ はMatcherオブジェクトを生成しますが、boolean値を要求するコンテキストでは、少なくとも1度のマッチがある場合"true"、
// そうでない場合"false"となります。
assert "cheesecheese" =~ "cheese"
assert "cheesecheese" =~ /cheese/
assert "cheese" == /cheese/ /* これは共に文字列として評価される*/
assert ! ("cheese" =~ /ham/)
// ==~ は、Stringがパターンにマッチするかどうかをテストします。
assert "2009" ==~ /\d+/ // TRUEを返します。
assert "holla" ==~ /\d+/ // FALSEを返します。
// Matcherオブジェクトを作成しましょう。
def matcher = "cheesecheese" =~ /cheese/
assert matcher instanceof Matcher
// 置換をいくつか行いましょう
def cheese = ("cheesecheese" =~ /cheese/).replaceFirst("nice")
assert cheese == "nicecheese"
assert "color" == "colour".replaceFirst(/ou/, "o")
def cheese = ("cheesecheese" =~ /cheese/).replaceAll("nice")
assert cheese == "nicenice"
// グループを使う簡単な例
// グループを含むパターンをマッチさせることができます。まずMatcherオブジェクトを生成し、
// Java API を使用するか、あるいはもっと簡単に =~ 演算子を使用します。そして、index値を使って
// Matcherオブジェクトからマッチを参照することができます。matcher[0]は文字列中で正規表現にマッチした
// 最初のマッチを表すリストを返します。そのリストの最初の要素は正規表現全体にマッチした文字列で、
// 残りの要素はそれぞれのグループにマッチした文字列です。
// 以下がその動作です。
def m = "foobarfoo" =~ /o(b.*r)f/
assert m[0] == ["obarf", "bar"]
assert m[0][1] == "bar"
// Matcherはリストではありませんが、Groovy 1.6 からリストのようにindex値を使うことができます。
// これには、index値としてコレクションを使うことも含みます。
def matcher = string =~ "e+"
assert "ee" == matcher[2]
assert ["ee", "e"] == matcher[2..3]
assert ["ee", "ee"] == matcher[0, 2]
assert ["ee", "e", "ee"] == matcher[0, 1..2]
matcher = "cheese please" =~ /([^e]+)e+/
assert ["se", "s"] == matcher[1]
assert [["se", "s"], [" ple", " pl"]] == matcher[1, 2]
assert [["se", "s"], [" ple", " pl"]] == matcher[1 .. 2]
assert [["chee", "ch"], [" ple", " pl"], ["ase", "as"]] == matcher[0, 2..3]
// Matcherはiterator()メソッドを定義しているため、例えばcollect()メソッド、
// each()メソッドなどを使うことができます。
matcher = "cheese please" =~ /([^e]+)e+/
matcher.each { println it }
matcher.reset()
assert matcher.collect { it } ==
[["chee", "ch"], ["se", "s"], [" ple", " pl"], ["ase", "as"]]
// Groovy 1.6 でイテレータのセマンティクスが変更されました。
// 1.5では、それぞれのイテレーションはグループを無視して、常にマッチした全体の文字列を返していました。
// 1.6では、正規表現にグループが含まれていれば、イテレーションは上記のように文字列のリストを返します。
// there is also regular expression aware iterator grep() イテレータのgrep()メソッドでも正規表現を使います。
assert ["foo", "moo"] == ["foo", "bar", "moo"].grep(~/.*oo$/)
// which can be written also with findAll() method 同じことをfindAll()メソッドでも書くことができます。
assert ["foo", "moo"] == ["foo", "bar", "moo"].findAll { it ==~ /.*oo/ }
|
| Excerpt | ||
|---|---|---|
| ||
Since a Matcher coerces to a boolean by calling its find method, the =~ operator is consistent with the simple use of Perl's =~ operator, when it appears as a predicate (in 'if', 'while', etc.). The "stricter-looking" ==~ operator requires an exact match of the whole subject string. It returns a Boolean, not a Matcher. Regular expression support is imported from Java. Java's regular expression language and API is documented here. |
Matcherは *find()*メソッドをコールすることで強制的にboolean値となるため、(if文、while文ほかの)条件節として現れたとき、 =~ 演算子はPerlの =~ 演算子の単純な使用法と同じ働きをします。
”より厳密に働くように見える” ==~ 演算子は、対象文字列全体との正確なマッチを要求します。Matcherではなく、Booleanを返します。
正規表現のサポートは、Javaから取り込まれています。Javaの正規表現言語とAPIはここにドキュメントされています。
| Excerpt | ||
|---|---|---|
| ||
More Examples |
| Excerpt | ||
|---|---|---|
| ||
Goal: Capitalize words at the beginning of each line: |
目的: 各行の始めにある単語の語頭を大文字にします:
| Code Block |
|---|
def before='''
apple
orange
y
banana
'''
def expected='''
Apple
Orange
Y
Banana
'''
assert expected == before.replaceAll(/(?m)^\w+/,
{ it[0].toUpperCase() + ((it.size() > 1) ? it[1..-1] : '') })
|
| Excerpt | ||
|---|---|---|
| ||
Goal: Capitalize every word in a string: |
目的: 文字列中の全ての単語の語頭を大文字にします:
| Code Block |
|---|
assert "It Is A Beautiful Day!" ==
("it is a beautiful day!".replaceAll(/\w+/,
{ it[0].toUpperCase() + ((it.size() > 1) ? it[1..-1] : '') }))
|
| Excerpt | ||
|---|---|---|
| ||
Add .toLowerCase() to make the rest of the words lowercase |
単語の残りの部分を小文字にするために.toLowerCase() を追加します。
| Code Block |
|---|
assert "It Is A Very Beautiful Day!" ==
("it is a VERY beautiful day!".replaceAll(/\w+/,
{ it[0].toUpperCase() + ((it.size() > 1) ? it[1..-1].toLowerCase() : '') }))
|
| Excerpt | ||
|---|---|---|
| ||
Gotchas |
| Excerpt | ||
|---|---|---|
| ||
How to use backreferences with String.replaceAll() GStrings do not work as you'd expect: |
String.replaceAll() の後方参照の使い方では、GStringは期待通りに動作しません。
| Code Block |
|---|
def replaced = "abc".replaceAll(/(a)(b)(c)/, "$1$3") |
| Excerpt | ||
|---|---|---|
| ||
Produces an error like the following: |
これは次のようなエラーとなります。
... illegal string body character after dollar sign:
solution: either escape a literal dollar sign "\$5" or bracket the value expression "${5}" @ line ...
| Excerpt | ||
|---|---|---|
| ||
Solution: Use ' or / to delimit the replacement string: |
解決法:
置換文字列を ' か / で括るようにします。
| Code Block |
|---|
def replaced = "abc".replaceAll(/(a)(b)(c)/, '$1$3') |