YAML の構文を押さえる : 文字列をクォートで囲む必要はない
YAML の構文を改めて勉強。
このサイトで実際に変換しながら確認した。
目次
文字列に関して
- 文字列はシングルクォートで囲んでも、ダブルクォートで囲んでも、囲まなくても、同じ
- Ansible においては、ダブルクォートで囲まないと変数展開されなかったりする
- このようにパースするライブラリ側での都合はあれど、YAML の言語仕様的にはクォートはあってもなくても同じ
- クォートで囲まない場合、シングルクォートやダブルクォート、その他の記号は基本的にエスケープせずそのまま書いて良い
- 行頭や行末をスペースで終わりたい場合はクォートで囲む
- シングルクォートで囲んでいる時にシングルクォートを使うには、シングルクォートを2つ書く
''
。バックスラッシュではエスケープにならないので注意
以下の Stackoverflow が分かりやすかった。
plain scalars:
- a string
- a string with a \ backslash that doesn't need to be escaped
- can also use " quotes ' and $ a % lot /&?+ of other {} [] stuff
single quoted:
- '& starts with a special character, needs quotes'
- 'this \ backslash also does not need to be escaped'
- 'just like the " double quote'
- 'to express one single quote, use '' two of them'
double quoted:
- "here we can use predefined escape sequences like \t \n \b"
- "or generic escape sequences \x0b \u0041 \U00000041"
- "the double quote \" needs to be escaped"
- "just like the \\ backslash"
- "the single quote ' and other characters must not be escaped"
literal block scalar: |
a multiline text
line 2
line 3
folded block scalar: >
a long line split into
several short
lines for readability
ハッシュ (マップ・連想配列) とリスト (配列)
ハッシュ (マップとか、連想配列とか) は、その階層で key: value
を繋げて書けば良い。
hoge: hogeValue
fuga: fugaValue
↓ コレは JSON に変換するとこうなる。
{
"hoge": "hogeValue",
"fuga": "fugaValue"
}
リスト (配列) はハイフンとスペースで始める。
- hoge
- fuga
↓ JSON に変換するとこうなる。
[
"hoge",
"fuga"
]
ハッシュをリストとして定義。
- hoge: hogeValue
hogeDescription: This is hoge.
- fuga: fugaValue
fugaDescription: This is fuga.
↓ JSON に変換するとこう。
[
{
"hoge": "hogeValue",
"hogeDescription": "This is hoge."
},
{
"fuga": "fugaValue",
"fugaDescription": "This is fuga."
}
]
ハッシュをネストする時のインデントが若干分かりづらいかもしれない。
- name: My Services 1
services:
- name: my-services-1-A
enabled: true
- name: my-services-1-B
enabled: false
- name: My Services 2
services:
- name: my-services-2-A
enabled: false
- name: my-services-2-B
enabled: true
services:
の配下にある「ハッシュのリスト」は、services
の行頭と同じインデントになっていたり、1段階ネストを下げたりしているが、どちらも階層構造は変わらず、次のように JSON 化して表現できる。
[
{
"name": "My Services 1",
"services": [
{
"name": "my-services-1-A",
"enabled": true
},
{
"name": "my-services-1-B",
"enabled": false
}
]
},
{
"name": "My Services 2",
"services": [
{
"name": "my-services-2-A",
"enabled": false
},
{
"name": "my-services-2-B",
"enabled": true
}
]
}
]
フロースタイル
上述のような書き方をブロックスタイルという。一方、1行にまとめてリストやハッシュを書けるフロースタイルという書き方もある。
nameList1: [Jane Doe, Foo Bar]
nameList2: ['Jane Doe', "Foo, Bar"]
profileHash1: { name: Jane Doe, age: 22 }
profileHash2: { name: "Foo, Bar", age: 30 }
リスト []
とハッシュ {}
を1行で書ける。
- 値はクォートを書いても、クォートなしで書いても同じ (通常と同じ)
- カンマ
,
が配列の要素、Key・Value の区切りとなるので、カンマを含む値を書く場合はクォートで囲むこと- 上の例だと
Foo, Bar
はカンマを含んだ値になっている。コレを正しく解釈させるにはカンマが必要
- 上の例だと
- ハッシュの場合はコロン
:
も区切り文字になるので、値に含める場合はクォートで囲む- Key の方にカンマやコロンを含めたい場合も、クォートで囲めば良い。
profileHash: { 'user:name': Michael, "user,age": '30' }
のように
- Key の方にカンマやコロンを含めたい場合も、クォートで囲めば良い。
次のように JSON 変換できる。
{
"nameList1": [
"Jane Doe",
"Foo Bar"
],
"nameList2": [
"Jane Doe",
"Foo, Bar"
],
"profileHash1": {
"name": "Jane Doe",
"age": 22
},
"profileHash2": {
"name": "Foo, Bar",
"age": 30
}
}
パイプ記号 |
による複数行リテラル
パイプ記号 |
を使うと複数行のテキストを書ける。
first: |
hoge
fuga
foo
bar
second: | hoge |
third: |fuga|
コレを JSON 化するとこうなる。
{
"first": "hoge\n fuga\nfoo\n bar\n",
"second": "| hoge |",
"third": "|fuga|"
}
first: |
の次の行、hoge
は1つ以上のスペースを開けて書く。大抵は2スペースを開けて書くことが多いかな。コレがインデントの始点となり、以降の行に登場する先頭のスペースは無視される。その証拠に、JSON データを見ると、foo
は hoge
と同じスペース数なので、行頭にスペースがない。一方、fuga
と bar
の行は行頭に hoge
以上のスペースがあるので、それが残っている。
second
と third
は、いきなりパイプ記号 |
を使ったとしても、その後に改行 + インデントが登場しなければ単に文字列として認識されるという例。なんだかこの辺の解釈が優秀すぎて、覚えきれないんだよなぁ。思ったとおりに解釈されているのかが JSON よりも不安な感じ。w
大なり記号 >
による折りたたみスタイル
大なり記号 >
を使うと、複数行で書いたテキストも1行にまとめてくれる。
single-data: >
aaa
bbb
ccc
ddd
eee
JSON 化するとこんな感じ。
{
"single-data": "aaa bbb ccc ddd\neee\n"
}
>
の行よりも多いインデントを付けておいて複数行書いていくと、そのインデント位置を始点に、改行を1スペースとして変換して出力する。それが aaa bbb ccc
部分で分かる。
一方、ddd
の行は行頭に2つ多くスペースを置いたので、その2つのスペースが残って ccc ddd
(スペース2つ) で残った。そしてその後続の eee
については、インデントが戻ったので改行コード \n
が入った。