3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Ansible Tips: dictionary や list_of_dictionaries 構造などにおいて使用できるフィルターなど

Last updated at Posted at 2021-07-10

備忘

dictionary や list_of_dictionaries 構造などにおいて使用できるフィルターなど

- hosts: all
  gather_facts: false
  tasks:

# list -> 全要素の数
  # |length

  - debug: { msg: "{{ [ 0, 1, 2, ]|length }}" }                   # "3" 


# list -> 特定の要素の数
  # .count()

  - debug: { msg: "{{ ['a', 'b', 'c', 'b'] .count('b') }}" }      # "2"      listにおける要素の数


# list -> 要素の場所(最初)
  # .index()

  - debug: { msg: "{{ ['a', 'b', 'c', 'b'] .index('b') }}" }      # "1"      listにおけるその値の要素の最初の場所。0始まり。


# list -> 特定の場所の要素
  # []
  # |first
  # |last

  - debug: { msg: "{{ ['a', 'b', 'c', 'd'][1] }}" }               # "b"      listにおけるその場所(0始まり)の値
  - debug: { msg: "{{ ['a', 'b', 'c', 'd'][-2] }}" }              # "c"      マイナスの場合は末尾から(-1始まり)
  - debug: { msg: "{{ ['a', 'b', 'c', 'd']|first }}" }            # "a"      [0]と同じ
  - debug: { msg: "{{ ['a', 'b', 'c', 'd']|last }}" }             # "d"      [-1]と同じ


# list -> 逆順のlist
  # |reverse

  - debug: { msg: "{{ ['a', 'b']|reverse }}" }                    # ['b', 'a']    listにおける要素を逆順に


# list -> 値が指定条件を満たすlistを抽出
  # |select()

  - debug: { msg: "{{ ['a', 'b', 'c'] | select('==','b') }}" }    # ["b"]
  - debug: { msg: "{{ ['a', 'b', 'b'] | select('==','b') }}" }    # ["b", "b"]
  - debug: { msg: "{{ ['a', 'b', 'c'] | select('==','d') }}" }    # []
  - debug: { msg: "{{ ['c', 'b', 'a'] | select('<=','b') }}" }    # ["b", "a"]
  - debug: { msg: "{{ ['c', 'b', 'a'] | select('>=','b') }}" }    # ["c", "b"]
  - debug: { msg: "{{ ['c', 'b', 'a'] | select('<','b') }}" }     # ["a"]
  - debug: { msg: "{{ ['c', 'b', 'a'] | select('>','b') }}" }     # ["c"]
  - debug: { msg: "{{ ['a', '(b)', 'c'] | select('match', '\\(.*\\)') | list }}" } # ["(b)"]

        # https://jinja.palletsprojects.com/en/3.0.x/templates/#jinja-filters.select

        # 使えるテストは以下という理解だが、matchが見当たらない^^;
        # https://jinja.palletsprojects.com/en/3.0.x/templates/#list-of-builtin-tests

        # Ansibleにより提供されたフィルターか
        # https://docs.ansible.com/ansible/2.9_ja/user_guide/playbooks_tests.html#testing-strings


# list -> 各要素にfilterを適用したlistを作成
  # |map()

  - debug: { msg: "{{ ['a', 'b', 'c'] | map('upper') }}" }       # [ "A", "B", "C" ]  # filterへの引数はmap内で","区切りで指定
 
        # https://jinja.palletsprojects.com/en/3.0.x/templates/#jinja-filters.map

# listと値 -> (listの要素をkeyとする)dictを作成
  # .fromkeys()

  - debug: { msg: "{{ {}.fromkeys(['a','b'],0) }}" }              # { "a": 0, "b": 0 }                listの要素をキーとするdictを作成
  - debug: { msg: "{{ {}.fromkeys(['a','b'],[7,8]) }}" }          # { "a": [ 7, 8 ], "b": [ 7, 8 ] }  listの要素をキーとするdictを作成

# list -> dict
  # items2dict
  # https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#transforming-lists-into-dictionaries
# dict -> 特定のkeyのvalueを抽出
  # []
  # .KEY
  # .get()

  - debug: { msg: "{{ {'k0': 'v0', 'k1': 'v1'}['k1'] }}" }        # "v1"
  - debug: { msg: "{{ {'k0': 'v0', 'k1': 'v1'}.k1 }}" }           # "v1"  注: 指定キーが予約語(例えばindexなど)と重複する場合、この書式は使用できない
  - debug: { msg: "{{ {'k0': 'v0', 'k1': 'v1'}.get('k1') }}" }    # "v1"



# list_of_dict -> 特定のkeyに対応するvalueを抜き出してlistを作成
  # |map(attribute=KEY)

  - debug: { msg: "{{ [{'k1': 'v11', 'k2': 'v12'}, {'k1': 'v21', 'k2': 'v22'}]|map(attribute='k2')|list }}" }       # [ "v12", "v22" ] なお、"|list"は新しいansibleでは不要かも


# list_of_dict -> 指定したkeyに関してグルーピングしたlistを作成
  # |groupby()

  - debug:
      msg: "{{ address_book|groupby('addr') }}"
    vars:
      address_book:
      - {name: foo, addr: tok}
      - {name: bar, addr: tok}
      - {name: baz, addr: chiba}
    register: r

        # 結果
        # - - chiba
        #   - - {name: baz, addr: chiba}
        # - - tok
        #   - - {name: foo, addr: tok}
        #     - {name: bar, addr: tok}


# list_of_dict -> 特定の要件を満たす部分集合
  # |selectattr(key,test,arg)
  # |rejectattr(key,test,arg)

  # testには、==などの他にinやcontainsといったものも使用可能
# https://zaki-hmkc.hatenablog.com/entry/2021/02/18/000228



# dict ->  keysのlistを作成
  # .keys()

  - debug: { msg: "{{ {'k0': 'v0', 'k1': 'v1'}.keys() }}" }       # ["k0", "k1"]


# dict ->  valesのlistを作成
  # .values()

  - debug: { msg: "{{ {'k0': 'v0', 'k1': 'v1'}.values() }}" }     # ["v0", "v1"]


# dict -> [キー, 値]のlistに変換
  # .items()

  - debug: { msg: "{{ {'k0': 'v0', 'k1': 'v1'}.items() }}" }      # [["k0", "v0"], ["k1", "v1"]]
  - debug: { msg: "{{ {'k1': 'v1', 'k0': 'v0'}.items() }}" }      # [["k1", "v1"], ["k0", "v0"]] # 順序が考慮されていて上の行と同じ結果でない。バージョンなどにより結果が異る可能性。


# dict -> key:,value:書式dictのlistを作成 (loop:の引数などに利用可能)
  # |dict2items
  # https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#transforming-dictionaries-into-lists

    #   k0: v0
    #   k1: v1
    #   ↓
    #   - key: k0
    #     value: v0
    #   - key: k1
    #     value: v1

  - debug: { msg: "{{ {'k0': 'v0', 'k1': 'v1'}|dict2items|list }}" } # [{"key": "k0", "value": "v0"}, {"key": "k1", "value": "v1"}] なお、"|list"は新しいansibleでは不要かも

# key,valueのlistのlistをdictに変換
  # dict(...)
  # https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#combining-items-from-multiple-lists-zip-and-zip-longest

    # - - k0
    #   - v0
    # - - k1
    #   - v1
    # ↓
    # k0: v0
    # k1: v1

  - debug: { var: dict( [['k1','v1'], ['k2','v2']] ) }    # => { "k1": "v1", "k2": "v2" }


# ある要素がキー->下位listとなっているlist -> そのキー以下のlistを用いた疑似2重ループ用のデータに変換
  # |subelements(キー)  
  # https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#combining-objects-and-subelements

  - debug:
      msg: "{{ users|subelements('groups') }}"
    vars:
      users:
        - name: user1
          groups: [wheel, hoge]
        - name: user2
          groups: [hoge]

        # 結果
        # - - name: user1
        #     groups: [wheel, hoge]
        #   - wheel
        # - - name: user1
        #     groups: [wheel, hoge]
        #   - hoge
        # - - name: user2
        #     groups: [hoge]
        #   - hoge


# dict -> changedキーやfailedキーなどに対する値(true/false)
  # is changed
  # ['changed']
  # .changed

  - debug: { msg: "{{ {'changed': true } is changed }}" }         # true
  - debug: { msg: "{{ {'changed': false} is changed }}" }         # false
  - debug: { msg: "{{ {                } is changed }}" }         # false  'changed'キーがなくともエラーにならない
  - debug: { msg: "{{ {                } is not changed }}" }     # true   'changed'キーがなくともエラーにならない
  - debug: { msg: "{{ {'changed': true }['changed'] }}" }         # true
  - debug: { msg: "{{ {'changed': true }.changed }}" }            # true
# - debug: { msg: "{{ {                }.changed }}" }            # 'dict object' has no attribute 'changed'


# 要素1が集合2に含まれるかどうか、文字列string1がstring2 に含まれるかどうか
  # 要素 in 集合
  # string1 in string2
  # string1.find(string2)

  - debug: { msg: "{{ 'a' in ['a', 'b', 'c'] }}" }                # true
  - debug: { msg: "{{ 'z' in ['a', 'b', 'c'] }}" }                # false
# - debug: { msg: "{{ ['a', 'b', 'c'].find('a') }}" }             # 'list object' has no attribute 'find'

  - debug: { msg: "{{ 'ab' in 'abcd' }}" }                        # true
  - debug: { msg: "{{ 'ba' in 'abcd' }}" }                        # false
  - debug: { msg: "{{ 'ab' not in 'abcd' }}" }                    # false
  - debug: { msg: "{{ 'abcd'.find('ab') }}" }                     # 0
  - debug: { msg: "{{ 'abcd'.find('ba') }}" }                     # -1

        # https://jinja.palletsprojects.com/en/3.0.x/templates/#jinja-tests.in


# 型の表示

  - debug: { msg: "{{ 1|type_debug }}" }                          # "int"
  - debug: { msg: "{{ []|type_debug }}" }                         # "list"
  - debug: { msg: "{{ {}|type_debug }}" }                         # "dict"
  - debug: { msg: "{{ true|type_debug }}" }                       # "bool"
  - debug: { msg: "{{ 'abc'|type_debug }}" }                      # "str"
  - debug: { msg: "{{ 'あいうえお'|type_debug }}" }                 # "str"
  - debug: { msg: "{{ foo|type_debug }}" }                        # "int"
    vars: { foo: 1 }
  - debug: { msg: "{{ foo|type_debug }}" }                        # "int"
    vars: { foo: "{{ bar }}", bar: 2 }
  - debug: { msg: "{{ foo|type_debug }}" }                        # "AnsibleUnicode"
    vars: { foo: abc }


# 構造化データ -> string
  # |to_nice_yaml  # ブロックスタイルYAML書式の文字列に変換
  # |to_yaml       # 下層にフロースタイルを混ぜてより短く表示。個人的にはto_nice_yamlより改行が少く見通しがかなり良い。


# string -> 構造化データ
  # |from_yaml     # YAML形式の文字列を解釈
  # |from_json     # JSON形式の文字列を解釈


# 一般的と思われるもの

# == もしくは eq
# != もしくは ne 
# >  もしくは gt
# <  もしくは lt
# >= もしくは ge
# <= もしくは le

# https://jinja.palletsprojects.com/en/3.0.x/templates/#list-of-builtin-filters

# |basename
# |dirname

# |int
# |float
# |bool
# |string

# |sort()

# |join()

# |lower
# |upper

# |b64decode

# |max
# |min
# |sum


# 以下未完

# dict -> キーで並び換え  本来dictsは順序を持たず、実際Pythonでは順序は保証されないが、for loopなどで順序を使用したい場合に使用。
  # |dictsort  

# 複数の構造化データ -> 単一の構造化データ
  # h1|combine(h2,h3,..)  
  # [h1,h2,h3,...]|combine  
# 複数の構造化データ -> 単一の構造化データ  Deepマージ
  # h1|combine(h2,h3,.. ,recursive=true)  
  # [h1,h2,h3,...]|combine(recursive=true)  
  # https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#combining-hashes-dictionaries

# 構造化データをより高度に扱う
  # |json_query()

# 変数が未定義の場合のデフォルト値
  # |default(値) 
  # |default(omit)   # 特殊: 未定義の場合にその設定そのものを取り止め
# https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#providing-default-values
# https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#making-variables-optional

# string -> 正規表現による置き換え
  # |regex_replace('^.* = +(.*)$','\\1') 
  # |regex_replace('.yml')

# 多重階層のデータをフラット化
  # |flatten(levels=0)  

# プラグイン
  # https://docs.ansible.com/ansible/2.9_ja/plugins/lookup/pipe.html

  # lookup('env', 'PWD')  
  # lookup('pipe', 'date')  


# https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html

# 3項演算
  # | ternary(x,y[,z]) # zは値がnullの場合
  # x if 式 else y
  # https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#defining-different-values-for-true-false-null-ternary

# set もしくは list
  # https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#selecting-from-sets-or-lists-set-theory

# listから重複削除
  # uniq
# 和集合
  # union
# 積集合
  # intersect
# 差集合
  # | difference
# 排他的論理和
  # | symmetric_difference


# 複数のlistから要素を1:1で抜き出したもののlistを作成
  # | zip()|list
  # | zip_longest()|list
  # https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#combining-items-from-multiple-lists-zip-and-zip-longest


# 2要素listのlistからdictを作成
  # dict()

- debug: { var: dict([['k1','v1'],['k2','v2']]) }  # => {"k1": "v1", "k2": "v2"}

参考

3
3
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
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?