Corredor

ウェブ、プログラミングの勉強メモ。

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' } のように

次のように 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 データを見ると、foohoge と同じスペース数なので、行頭にスペースがない。一方、fugabar の行は行頭に hoge 以上のスペースがあるので、それが残っている。

secondthird は、いきなりパイプ記号 | を使ったとしても、その後に改行 + インデントが登場しなければ単に文字列として認識されるという例。なんだかこの辺の解釈が優秀すぎて、覚えきれないんだよなぁ。思ったとおりに解釈されているのかが 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 が入った。

参考文献

Ansible徹底活用ガイド ThinkIT Books

Ansible徹底活用ガイド ThinkIT Books

  • 作者: 平初,平原一帆,小野寺大地,安久隼人,坂本諒太,冨永善視
  • 出版社/メーカー: インプレス
  • 発売日: 2016/10/04
  • メディア: Kindle版
  • この商品を含むブログを見る