Ansible Tips: jinja2 '{{ }}' 中において改行コード \n を表す

備忘



# 問題 '{{ }}'中の"\n"が改行コード(LF)として認識されなかった



## 例

```yaml
- hosts: all
  gather_facts: false
  vars:
    lines: |-
      l1
      l2
  tasks:

  - name: シングルクォートで全体を囲うと\n 改行コードが正しく認識されず行で分割されない
    debug:
      msg: '{{ lines | split("\n") }}'
```




```
TASK [シングルクォートで全体を囲うと\n 改行コードが正しく認識されず行で分割されない] ***************************************************
ok: [localhost] => {
    "msg": [
        "l1\nl2"
    ]
}
```
YAMLで > や | などを使用した連結や複数行の際もシングルクォート相当となるため、注意が必要



# 対応1 "{{ }}"中の'\n'であれば改行コード(LF)として認識される

## 例

```yaml
- hosts: all
  gather_facts: false
  vars:
    lines: |-
      l1
      l2
  tasks:

  - name: シングルクォートで全体を囲うと\n 改行コードが正しく認識されず行で分割されない
    debug:
      msg: '{{ lines | split("\n") }}'

  - name: "全体をダブルクォートで囲うと改行コードが正しく認識され分割される"
    debug:
      msg: "{{ lines | split('\n') }}"
```

```
TASK [シングルクォートで全体を囲うと\n 改行コードが正しく認識されず行で分割されない] ***************************************************
ok: [localhost] => {
    "msg": [
        "l1\nl2"
    ]
}

TASK [全体をダブルクォートで囲うと改行コードが正しく認識され分割される] ****************************************************************
ok: [localhost] => {
    "msg": [
        "l1",
        "l2"
    ]
}
```
シンプル。ただし > や | を使用した連結や複数行の際には利用できない。

# 対応2 シングルクォート中で実際に改行する対応

```
  - name: "全体をシングルクォートで囲っても改行コードを正しく認識させ行で分割させる書き方1"
    vars:
      lines: |-
        l1
        l2
    debug:
      msg: '{{ lines|split("

        ") }}'
```

```
TASK [全体をシングルクォートで囲っても改行コードを正しく認識させ行で分割させる書き方1] *************************************************
ok: [localhost] => {
    "msg": [
        "l1",
        "l2"
    ]
}
```
可読性は低くなるが、直接改行することで対応可能。

# 対応3 別変数に収納しておく
```
  - name: "> などを用いても改行コードを正しく認識させ行で分割させる書き方5"
    vars:
      lines: |-
        l1
        l2
      lf: "\n"
    debug:
      msg: >-
        {{ lines | split(lf) }}
```

```
TASK [> などを用いても改行コードを正しく認識させ行で分割させる書き方5] *****************************************************************
ok: [localhost] => {
    "msg": [
        "l1",
        "l2"
    ]
}
```
task varsやjinja2のsetで一旦 "\n" を変数に収納して利用すれば、正しく扱われる

# 参考playbook
```yaml
- hosts: all
  gather_facts: false
  vars:
    lines: |-
      l1
      l2
  tasks:

  - name: "全体をダブルクォートで囲うと改行コードが正しく認識され分割される"
    debug:
      msg: "{{ lines | split('\n') }}"


  - name: "しかし、全体をシングルクォートで囲うと改行コードが正しく認識されず行で分割されない1"
    debug:
      msg: '{{ lines | split("\n") }}'

  - name: "改行コードが正しく認識されず行で分割されない2"
    debug:
      msg: '{{ lines | split(''\n'') }}'
      #msg: "{{ lines | split('\\n') }}"    # ansible-lint --fixではこの様に修正される


  - name: "また、> などは'による解釈と同等であり分割されない3"
    debug:
      msg: >
        {{ lines|split("\n") }}

  - name: "> などとシングルクォーテーションの組み合わせでも分割されない4"
    debug:
      msg: >
        {{ lines|split('\n') }}


  - name: "全体をシングルクォートで囲っても改行コードを正しく認識させ行で分割させる書き方1"
    debug:
      msg: '{{ lines|split("

        ") }}'
      #msg: "{{ lines|split(\"\n\") }}"     # ansible-lint --fixではこの様に修正される

  - name: "全体をシングルクォートで囲っても改行コードを正しく認識させ行で分割させる書き方2"
    debug:
      msg: '{{ lines|split(''

        '') }}'
      #msg: "{{ lines|split('\n') }}"       # ansible-lint --fixではこの様に修正される

  - name: "全体をシングルクォートで囲っても改行コードを正しく認識させ行で分割させる書き方3"
    debug:
      msg: '{% set lf = "\n" %}{{ lines | split(lf) }}'

  - name: "> などを用いても改行コードを正しく認識させ行で分割させる書き方4"
    debug:
      msg: >-
        {{ lines | split("

        ") }}

  - name: "> などを用いても改行コードを正しく認識させ行で分割させる書き方5"
    vars:
      lf: "\n"
    debug:
      msg: >-
        {{ lines | split(lf) }}

  - name: "> などを用いても改行コードを正しく認識させ行で分割させる書き方6"
    debug:
      msg: >-
        {% set lf = "\n" %}{{ lines | split(lf) }}
```
# 参考の出力結果
```
TASK [全体をダブルクォートで囲うと改行コードが正しく認識され分割される] ****************************************************************
ok: [localhost] => {
    "msg": [
        "l1",
        "l2"
    ]
}

TASK [しかし、全体をシングルクォートで囲うと改行コードが正しく認識されず行で分割されない1] *********************************************
ok: [localhost] => {
    "msg": [
        "l1\nl2"
    ]
}

TASK [改行コードが正しく認識されず行で分割されない2] ***********************************************************************************
ok: [localhost] => {
    "msg": [
        "l1\nl2"
    ]
}

TASK [また、> などは'による解釈と同等であり分割されない3] ******************************************************************************
ok: [localhost] => {
    "msg": [
        "l1\nl2"
    ]
}

TASK [> などとシングルクォーテーションの組み合わせでも分割されない4] *******************************************************************
ok: [localhost] => {
    "msg": [
        "l1\nl2"
    ]
}

TASK [全体をシングルクォートで囲っても改行コードを正しく認識させ行で分割させる書き方1] *************************************************
ok: [localhost] => {
    "msg": [
        "l1",
        "l2"
    ]
}

TASK [全体をシングルクォートで囲っても改行コードを正しく認識させ行で分割させる書き方2] *************************************************
ok: [localhost] => {
    "msg": [
        "l1",
        "l2"
    ]
}

TASK [全体をシングルクォートで囲っても改行コードを正しく認識させ行で分割させる書き方3] *************************************************
ok: [localhost] => {
    "msg": [
        "l1",
        "l2"
    ]
}

TASK [> などを用いても改行コードを正しく認識させ行で分割させる書き方4] *****************************************************************
ok: [localhost] => {
    "msg": [
        "l1",
        "l2"
    ]
}

TASK [> などを用いても改行コードを正しく認識させ行で分割させる書き方5] *****************************************************************
ok: [localhost] => {
    "msg": [
        "l1",
        "l2"
    ]
}

TASK [> などを用いても改行コードを正しく認識させ行で分割させる書き方6] *****************************************************************
ok: [localhost] => {
    "msg": [
        "l1",
        "l2"
    ]
}

```

# 確認を行った環境
```
% ansible --version
ansible [core 2.15.5]
...
  python version = 3.9.6 ...
  jinja version = 3.1.2
...
```