CLOVER🍀

That was when it all began.

Groovyのヒアドキュメント

Groovyを使った場合のヒアドキュメント、なぜか毎度覚えられずにシェルスクリプトとかPHPと混じったりしてるので、ちょっと自分のために整理してみました。

Strings and GString
http://groovy.codehaus.org/Strings+and+GString

ドキュメント上では、「ヒアドキュメント」なんて一言も言ってませんし、単に複数行で書けるStringだよという話なのですが、探す時のキーワードってだいたい「ヒアドキュメント」ですよね…。

なお、ここで使用するコード例では、あらかじめ変数として

def variable = "Hello World"

が宣言されているものとします。

確認環境は、

$ groovy -version
Groovy Version: 2.1.6 JVM: 1.7.0_25 Vendor: Oracle Corporation OS: Linux

です。

3パターンの書き方

Groovyでは、ヒアドキュメントの書き方として3つ書き方があります。それぞれ性格が違うので、簡単にご紹介。

"""string"""

ダブルクォート(")を、3つ使う書き方です。以下、サンプル。

def multiLineString = """これは
複数行の
"文字列"です

変数は展開されます
variable = $variable

バックスラッシュはエスケープ文字となります
\r\n

そんな文字列"""

出力してみると

println("----------")
println(multiLineString)
println("----------")

こんな結果になります。

----------
これは
複数行の
"文字列"です

変数は展開されます
variable = Hello World

バックスラッシュはエスケープ文字となります



そんな文字列
----------

なので、特徴として

  • GStringの展開がある
  • /はエスケープ文字となる

ということになります。
*複数行が書けるというのも特徴なのですが、全部同じことが言えるので書きません…

なお、

"文字列"です

みたいに、ダブルクォートがエスケープなしで使えるというところがポイントでは?

某言語ができてたので、試してみたらやっぱりできました(笑)。

ダブルクォートでは終了することができないというところも、やっぱり同じ。まあ仕方ないよね。

'''string'''

シングルクォート(')を、3つ使う書き方です。以下、サンプル。

def multiLineStringNoExpand = '''これは
複数行の
'文字列'です

変数は展開しません
variable = $variable

バックスラッシュはエスケープ文字となります
\r\n

そんな文字列'''

出力

println("----------")
println(multiLineStringNoExpand)
println("----------")

結果。

----------
これは
複数行の
'文字列'です

変数は展開しません
variable = $variable

バックスラッシュはエスケープ文字となります



そんな文字列
----------

こちらは、

  • GStringの展開は行われない
  • /はエスケープ文字となる

という動きになります。あと、シングルクォートやダブルクォートのエスケープは、こちらも不要になってました。

$/string/$

$/と$/で囲う書き方です。以下、サンプル。

def multiLineStringNoEscape = $/これは
複数行の
"文字列"です

変数は展開します
variable = $variable

バックスラッシュはエスケープ文字となりません
\r\n

そんな文字列/$

出力

println("----------")
println(multiLineStringNoEscape)
println("----------")

結果。

----------
これは
複数行の
"文字列"です

変数は展開します
variable = Hello World

バックスラッシュはエスケープ文字となりません
\r\n

そんな文字列
----------

特徴としては、

  • GStringの展開は行われる
  • /はエスケープ文字とはならない

ですね。

これ、正規表現を使う時に重宝しそうな書き方ですが、

/string/

の方が多用されてそうな気がしますね。

続いて、知ってると便利そうなTipsを…。

あ、以降はprintlnしてる部分は、もう書きません。

先頭に「\」を入れる

ヒアドキュメントを使う時に、

def multiLineString2 = """
これは
複数行の
文字列です

変数は展開します
variable = $variable

バックスラッシュはエスケープ文字となります
\r\n

そんな文字列"""

みたいに最初に改行してしまうと

----------

これは
複数行の
文字列です

変数は展開します
variable = Hello World

バックスラッシュはエスケープ文字となります



そんな文字列
----------

みたいに最初に改行が入ってしまって、残念な結果になります。

これを抑制するためには、最初に「\」を入れます。3種類の書き方、どのパターンでも使えます。

"""string"""

def multiLineString3 = """\
これは
複数行の
文字列です

変数は展開します
variable = $variable

バックスラッシュはエスケープ文字となります
\r\n

そんな文字列"""

'''string'''

def multiLineStringNoExpand3 = '''\
これは
複数行の
文字列です

変数は展開しません
variable = $variable

バックスラッシュはエスケープ文字となります
\r\n

そんな文字列'''

$/string/$

def multiLineStringNoEscape3 = $/\
これは
複数行の
文字列です

変数は展開します
variable = $variable

バックスラッシュはエスケープ文字となりません
\r\n

そんな文字列/$

結果は、それぞれ

"""string"""

----------
これは
複数行の
文字列です

変数は展開します
variable = Hello World

バックスラッシュはエスケープ文字となります



そんな文字列
----------

'''string'''

----------
これは
複数行の
文字列です

変数は展開しません
variable = $variable

バックスラッシュはエスケープ文字となります



そんな文字列
----------

$/string/$

----------
これは
複数行の
文字列です

変数は展開します
variable = Hello World

バックスラッシュはエスケープ文字となりません
\r\n

そんな文字列
----------

となります。

$/string/$のパターンでは、最初の「\」は特別扱いしているみたいですね。

stripMargin

このメソッドを使用すると、特定の文字をデリミタとして、行頭を揃えることができるようになります。

某言語とメソッド名とデフォルトの文字が完全に同じなので、わかりやすかったです。

まずはオーソドックスな使用例を。

def multiLineString4 = """|これは
                          |複数行の
                          |文字列です

                          |変数は展開されます
                          |variable = $variable

                          |バックスラッシュはエスケープ文字となります
                          |\r\n

                          |そんな文字列""".stripMargin()

出力結果を見ると、何事もなかったかのように揃って出力されます。

----------
これは
複数行の
文字列です

変数は展開されます
variable = Hello World

バックスラッシュはエスケープ文字となります



そんな文字列
----------

これは、デフォルトのデリミタが「|」となっているからです。

stripMarginメソッドに引数にデリミタを渡すことで、自由に設定することができます。

def multiLineStringNoExpand4 = '''=これは
                                  =複数行の
                                  =文字列です

                                  =変数は展開しません
                                  =variable = $variable

                                  =バックスラッシュはエスケープ文字となります
                                  =\r\n

                                  =そんな文字列'''.stripMargin('=')
def multiLineStringNoEscape4 = $/-これは
                                -複数行の
                                -文字列です

                                -変数は展開します
                                -variable = $variable

                                -バックスラッシュはエスケープ文字となりません
                                -\r\n

                                -そんな文字列/$.stripMargin("-")
// stripMarginは、引数にStringを取れますが、実際には1文字分しか効果がありません

なお、stripMarginはcharとStringを引数に取るものがありますが、実際に機能するのは1文字のみで、String引数に複数文字を渡しても最初の1文字にしか機能しません。

…Groovyでは、charは書きづらいからでしょうね。

stripIndent

ヒアドキュメント内での最小幅の空白を、切り揃える機能です。

サンプル。

def multiLineString5 = """\
    これは
    複数行の
    文字列です

    変数は展開されます
    variable = $variable

    バックスラッシュはエスケープ文字となります
    \r\n

       最小幅で見ているらしいので、幅が大きいところはズレます

    そんな文字列""".stripIndent()

ひとつ、意図的に後ろにずらした行が入っています。

これを出力すると

----------
これは
複数行の
文字列です

変数は展開されます
variable = Hello World

バックスラッシュはエスケープ文字となります



   最小幅で見ているらしいので、幅が大きいところはズレます

そんな文字列
----------

という結果になり、幅が大きいところはそのままズレた形で出力されます。

ということで、最小幅で見ているので

def multiLineString5 = """\
    これは

みたいな感じで先頭を「\」で始めないと、あんまり意味のないメソッドかなぁと。これをやらなかった時点で、最小の幅は「0」になるので…。

削り取る幅は、自分で指定することもできます。

'''string'''

def multiLineStringNoExpand5 = '''\
    これは
    複数行の
    文字列です

    変数は展開しません
    variable = $variable

    バックスラッシュはエスケープ文字となります
    \r\n

       今度は幅を明示的に指定しています
ここ削除   が、最大幅に合わせてしまうと足りないところは削られてしまいます…

    そんな文字列'''.stripIndent(4)

なんですけど、ちゃんと幅を合わせておかないと削り取られるスペースにある文字は、容赦なく無くなってしまいます。

----------
これは
複数行の
文字列です

変数は展開しません
variable = $variable

バックスラッシュはエスケープ文字となります



   今度は幅を明示的に指定しています
   が、最大幅に合わせてしまうと足りないところは削られてしまいます…

そんな文字列
----------

$/string/$は、なんかうまく動いてなかったような…

def multiLineStringNoEscape5 = $/\
    これは
    複数行の
    文字列です

    変数は展開します
    variable = $variable

    バックスラッシュはエスケープ文字となりません
    \r\n

       今度は幅を明示的に指定しています
ここ削除   が、最大幅に合わせてしまうと足りないところは削られてしまいます…

    そんな文字列/$.stripIndent(4)

あれ??

----------
    これは
    複数行の
    文字列です

    変数は展開します
    variable = Hello World

    バックスラッシュはエスケープ文字となりません
    \r\n

       今度は幅を明示的に指定しています
ここ削除   が、最大幅に合わせてしまうと足りないところは削られてしまいます…

    そんな文字列
----------

これ、ちょっといろいろ試してみたのですが、$/string/$の場合は、変数が入っていて

    variable = $variable

かつ前に文字があったりするとダメで

ここ削除   が、最大幅に合わせてしまうと足りないところは削られてしまいます…

これらの行のいずれかを削除すると、指定分の文字が削除されました。この差は??

個人的には、stripMarginを使いそうかな〜?

今回の参考書籍は、もちろんこちらです。

プログラミングGROOVY

プログラミングGROOVY