倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

Groovy in Addiction (3) : 文字列

今回は文字列について。 『Groovyイン・アクション』Chapter3 を参考にしています(一覧)。

Groovyイン・アクション

Groovyイン・アクション

文字列リテラルの定義

開始・終了文字 GString
対応
エスケープ
必須文字
エスケープ
可能文字
使用箇所
シングルクォート (') × \b \t \r \n \f \\ \' \" \$ String リテラルの定義
ダブルクォート (") \b \t \r \n \f \\ \" \$ \' GString リテラルの定義
トリプルシングルクォート (''') × \b \t \r \n \f \\ \' \" \$ 複数行にわたる
String リテラルの定義
トリプルダブルクォート (""") \b \t \r \n \f \\ \$ \' \" 複数行にわたる
GString リテラルの定義
スラッシュ (/) \$ 正規表現の定義
  • Java ではシングルクォート構文は文字 (char) の定義
  • 複数行にわたるリテラルの定義では、プラットフォームによらず改行は \n として扱われる
  • スラッシュ構文でドル記号のエスケープが必要なのは、パターンの終わりを意味しないドル記号
  • どの場合でも Unicode エスケープ(\uxxxx : x は 0〜9, a〜d)は可能

宣言の例:

//***** シングルクォート *****
def s1 = 'Hello world !'
//***** ダブルクォート *****
def s2 = "Hello world, $name !"
//***** トリプルシングルクォート *****
def s3 = '''first line
second line
third line'''
//***** トリプルダブルクォート *****
def s4 = """1st line
2nd line
3rd line"""
//***** スラッシュ *****
def regex = /x(\d*)y/

java.lang.String


Groovy では、java.lang.String にいろいろメソッドが付加されています(Java API のメソッドも使用可)。 とはいっても、もちろん immutable。 ここではGroovyイン・アクション』付録C 「GDK API クイックリファレンス Groovy JDK を参考にしていくつか使用例を紹介。 以下で、独断と偏見による分類と、いくつかのメソッドのサンプルコードを見ていきます。

基本メソッド

何をもって基本とするか・・・はあんまり気にしないで。 ただ名前付けただけ。

メソッド 戻り値
size() int
contains(String) boolean
count(String) int
greeting = 'Hello Groovy !';

assert greeting.size() == 14;
assert greeting.contains('Groovy');
assert greeting.count('o') == 3;
assert greeting.count('oo') == 1;

演算子実装

前回紹介した「演算子実装」に関連するメソッド。

メソッド 戻り値 実装された演算子
getAt(int)
getAt(IntRange)
getAt(EmptyRange)
getAt(Range)
getAt(Collection)
String []
plus(Object) String +
minus(Object) String -
multiply(Number) String *
leftShift(Object) StringBuffer <<
previous() String --
next() String ++
isCase(Object) boolean switch-case
greeting = 'Hello Groovy !';

assert greeting[0] == 'H';
assert greeting[6..11] == 'Groovy';

assert 'Waman, ' + greeting == 'Waman, Hello Groovy !';
assert greeting - 'Hello ' == 'Groovy !';
assert 'x' * 3 == 'xxx';

StringBuffer buffer = greeting << ' waman';  // leftShift() メソッドの返り値は StringBuffer
assert  buffer.toString() == 'Hello Groovy ! waman';

// next()
s = 'waman';
s++
assert s == 'wamao';

// previous()
s = 'waman';
s--
assert s == 'wamam'

// switch-case
s = 'waman';
switch(s){
    case 'waman': assert true; break;
    case 'wamao': assert false; break;
    case 'wamam': assert false; break;
    default: assert false;
}

その他文字列に対する変更メソッド

「変更メソッド」といっても、String 自体が変更されるのではなく、変更された String オブジェクトが返されます(Java と同じ)。

メソッド 戻り値
center(Number)
center(Number, String)
String
padLeft(Number)
padLeft(Number, String)
String
padRight(Number)
padRight(Number, String)
String
normalize() String
denormalize() String
reverse() String
assert 'x'.center(3) == ' x ';  // 全部で3文字にする
assert 'xyzt'.center(3) == 'xyzt';  // 全部で4文字
assert 'x'.padLeft(5) == '    x';  // 全部で5文字にする
assert 'x'.padRight(5, '*') == 'x****';  // 全部で5文字にする

s = '\r \n \r\n';
assert s.normalize() == '\n \n \n';
assert s.denormalize() == '\r\n \r\n \r\n';  // on Windows

assert 'xyz'.reverse() == 'zyx';

文字列リスト・行関連のメソッド

メソッド 戻り値
getChars() char[]
toList() List
split() String[]
tokenize()
tokenize(String)
List
readLines() List
eachLine(Closure)
eachLine(int, Closure)
Object
//***** getChars(), toList() *****
s = 'waman';
assert s.getChars() == ['w', 'a', 'm', 'a', 'n'];    // 返り値は char[]
assert s.toList() == ['w', 'a', 'm', 'a', 'n'];    // 返り値は List<String>

//***** split(), tokenize() *****
line = 'Hello Groovy !';
assert line.split() == ['Hello', 'Groovy', '!'];    // 返り値は String[]
assert line.tokenize() == ['Hello', 'Groovy', '!'];    // 返り値は List<String>
assert line.tokenize('o') == ['Hell', ' Gr', 'vy !'];    // 'o' で分割

//***** readLines() *****
sentence = '''first line
second line
third line''';
assert sentence.readLines() == ['first line', 'second line', 'third line'];

//***** eachLine(Closure) *****
x = '';
sentence.eachLine {line -> 
    x += line - ' line'
    x += ' '
}
assert x == 'first second third ';

正規表現関連のメソッド

これは次回のサンプルで使用(たぶん)。

メソッド 戻り値
bitwiseNegate() Pattern
matches(Pattern) boolean
eachMatch(String, Closure)
eachMatch(Pattern, Closure)
String
splitEachLine(String, Closure)
splitEachLine(Pattern, Closure)
Object
find(String)
find(Pattern)
find(String, Closure)
find(Pattern, Closure)
String
findAll(String)
findAll(Pattern)
findAll(String, Closure)
findAll(Pattern, Closure)
List
replaceAll(Pattern, String)
replaceAll(String, Closure)
replaceAll(Pattern, Closure)
String
replaceFirst(Pattern, String) String

データ関連メソッド

コードガードメソッド (code guard method)」とは、型変換(一般的には何らかの処理)が例外なく行われるかどうかを確認するメソッド。 どの程度一般的に使われてる言葉なのか知りませんけど(笑)

データ型 コードガードメソッド
(返り値は boolean)
変換メソッド
(返り値は各データ型)
Boolean - toBoolean()
Character - toCharacter()
Number isNumber() -
Integer isInteger() toInteger()
Long isLong() toLong()
BigInteger isBigInteger() toBigInteger()
Float isFloat() toFloat()
Double isDouble() toDouble()
BigDecimal isBigDecimal() toBigDecimal()
URL - toURL()
URI - toURI()

サンプルは省略。

その他

メソッド 戻り値
asType(Class) Object
execute()
execute(List, File)
execute(String[], File)
Process
decodeBase64() byte[]

サンプルは省略。

StringBuffer, StringBuilder


immutable な java.lang.String に対して、変更の利く StringBuffer, StringBuilder クラスにも、いくつかメソッドが付加されてます。

メソッド 戻り値 実装された演算子
size() int
plus(String) String +
leftShift(Object) StringBuffer, StringBuilder <<
putAt(IntRange, Object)
putAt(EmptyRange, Object)
void [] =

サンプルコード:

greeting = 'Hello';

greeting <<= ' Groovy';  // greeting = greeting << ' Groovy' と同じ
assert greeting instanceof StringBuffer;  // << の返り値は StringBuffer

greeting << ' !';
assert greeting.toString() == 'Hello Groovy !';  // append(String) と同じ(かな?) 

greeting[1..4] = 'i';  // ello → i
assert greeting.toString() == 'Hi Groovy !';

groovy.lang.GString


GString のドル構文

GString はプレースホルダを持った文字列・・・くらいの認識でいいのかな? 

  • 省略形のドル構文:$xxxx
  • 省略形のドル構文(プロパティ・アクセス):$xxxx.yyyy
  • 中括弧{}を使った完全なドル構文:${xxxx.zzz()}
  • 複数行のGString:"""...."""
  • ドル記号を含むリテラル:"...\$..."

ドル構文」が正式名称なのかどうか不明(笑) それはそれとして、GString の使用例を。 まずはサンプルコードで用いるクラスの定義:

class Book{
    String title
    int price
    
    Book(String title, int price){
        this.title = title
        this.price = price
    }
    
    int getPriceIncludingTax(){
        return (int)(this.price * 1.25)
    }

    @Override String toString(){
        return '"'+this.title+'" '+this.price
    }
}

book = new Book('Groovy in Action', 5800);  // 以降のコード内での book はこのインスタンス

では GString のサンプルコードを:

//***** 省略形のドル構文 (1) *****
me = 'Tarzan';
you = 'Jane';
line = "me $me - you $you";
assert line == 'me Tarzan - you Jane';
//***** 省略形のドル構文 (2):オブジェクト *****
out = "Book: $book";
assert out == 'Book: "Groovy in Action" 5800';
        // オブジェクトに対しては toString() メソッドが呼ばれる
//***** 省略形のドル構文 (3):プロパティ・アクセス *****
out = """Title: "$book.title"; Price: $book.price""";
assert out == 'Title: "Groovy in Action"; Price: 5800'; 
//***** 中括弧{}を使った完全なドル構文 *****
out = "Price (tax included): ${book.getPriceIncludingTax()}";
assert out == 'Price (tax included): 7250';
//***** 複数行のGString *****
sql = """
SELECT FROM MyTable
    WHERE Price = $book.price
""";

assert sql == """
SELECT FROM MyTable
    WHERE Price = 5800
""";
//***** ドル記号を含むリテラル *****
out = "my 0.02\$";
assert out == 'my 0.02$'

GString のプロパティ

GString には

  • strings
  • values

という2つのプロパティが定義されてます(他にもあるかも知れませんが)。 細かい説明より、サンプル見た方が早いかな:

me = 'Tarzan';
you = 'Jane';
line = "me $me - you $you";

assert line == 'me Tarzan - you Jane';
assert line instanceof GString;

//***** strings プロパティ *****
assert line.strings[0] == 'me ';
assert line.strings[1] == ' - you ';

//***** values プロパティ *****
assert line.values[0] == 'Tarzan';
assert line.values[1] == 'Jane';

つまり、上記の GString「line」に対して

  • strings プロパティは「me_$me_-_you_$you」(空白はアンダーライン (_) にしてます)の強調部分
  • values プロパティは「me $me - you $you」の強調部分

となってます。