LoginSignup
229
140

More than 3 years have passed since last update.

YAMLで複数行テキストを書きたい時のあれこれ

Last updated at Posted at 2019-10-29

TL;DR

sample.yml
text0:
  吾輩は猫である
  名前はまだ無い
text1: |-
  吾輩は猫である
  名前はまだ無い
text2: >-
  吾輩は猫である
  名前はまだ無い
text3: "\
  吾輩は猫である\
  名前はまだ無い"
YAML.load_file('sample.yml')

=>
{
  "text0"=>"吾輩は猫である 名前はまだ無い",
  "text1"=>"吾輩は猫である\n名前はまだ無い",
  "text2"=>"吾輩は猫である 名前はまだ無い",
  "text3"=>"吾輩は猫である名前はまだ無い"
}

発端

Railsでの設定ファイルとして、Yaml形式がよく使われています。特にi18n用のファイルはよく長文を記述されます。しかし、長文を一行で書くことは保守上問題ですし、改行を入れて複数行にすると、変な改行やスペースが残されますし、今まではやむをえず、読み取り側で改行を取り除くロジックを組みました。
色々調べて、やっとこちらの回答にたどり着いた。

わかったこと

Yaml 複数行で検索すると、だいたいfoo: |foo: >を使いなさいと書かれるが、使い方は実は微妙でした。

foo: |foo: |-foo: |+

まずは基本形のfoo: |

foo: |
  bar
  baz

上記Yamlはこう解釈されます。

{ "foo": "bar\nbaz\n" }

-記号を追加すると、最後の改行が無くなります。

foo: |-
  bar
  baz
{ "foo": "bar\nbaz" }

+記号について

+記号は滅多に使われないが、その意味は最後に改行が複数ある場合、そのまま反映します。

foo: |
  bar
  baz


bar: 1
{ "foo": "bar\nbaz\n", "bar": 1 }
foo: |+
  bar
  baz


bar: 1
{ "foo": "bar\nbaz\n\n\n", "bar": 1 }

foo: >foo: >-foo: >+

foo: >シリーズもだいたい一緒で、foo: |との違いは、行末の改行がスペースになります。

foo: >
  bar
  baz
{ "foo": "bar baz\n" }

""''や何も書かない時

英語圏であれば、上記の2つで十分ですが、日本語で長文を書いて、改行をしたい時は、どうしても改行もスペースもなくなりたいので、次の方法でできます。

ヒントはHeredoc記法でした。

よくShellで、行末に\追加する手法があります。それはここで改行しませんという意味です。

cat <<DOC
foo\
bar
DOC

=> foobar

Yamlでは""で囲むと、似たような使い方ができます。

foo: "\
  bar\
  baz"

上記Yamlはこう解釈されます。

{ "foo": "barbaz" }

書き方は色々あります。例えば下記の書き方も可能です

foo: "bar\
  baz\
"

ちなみの行末の\がない時、改行がスペースと解釈されます。
もし改行が必要な場合、\nを入れましょう。

foo: "\
  b\nar\
  baz\
"
{ "foo": "b\narbaz" }

余談ですが、Rubyの仕様と同じように''で囲むとき、改行がスペースになり、\nなどエスケープ文字は全部解釈されなくなります。

foo: '\
  bar\
  baz\
'
{ "foo": "\\ bar\\ baz\\ " }

何も書かない時も、実は複数行の記入も可能でした。

foo:
  bar\
  baz
{ "foo": "bar\\ baz" }

改行がスペースになる、エスケープ文字は解釈しない、そして最初と最後の改行は無視されます。

最後に

こちらの回答はいろんなニッチな使い方も羅列しており、ぜひ読んでみてください。

参考

229
140
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
229
140