如何通过Ansible循环及过滤器生成指定结构的目标字典?
问题描述
现有如下列表:
ids: [id1, id2, id3]
以及Ansible迭代后注册的结果output2:
output2: changed: false msg: All items completed results: - ansible_loop_var: item changed: false failed: false item: id1 msg: json: key1: '0' key2: '6' key3: '4' - ansible_loop_var: item changed: false failed: false item: id2 msg: json: key1: '2' key2: '6' key3: '6' - ansible_loop_var: item changed: false failed: false item: id3 msg: json: key1: '8' key2: '0' key3: '9' skipped: false
需要生成指定结构的字典,并筛选出key1和key3:
"id1": { "key1": "0", "key3": "4" } "id2": { "key1": "2", "key3": "6" } "id3": { "key1": "8", "key3": "9" }
解决方案
方法一:Jinja2字典推导式(易读版)
通过set_fact结合Jinja2的循环逻辑,直观地重组目标结构:
- name: 生成目标结构字典 set_fact: target_dict: >- {% set result = {} %} {% for res in output2.results %} {% set _ = result.update({ res.item: { 'key1': res.msg.json.key1, 'key3': res.msg.json.key3 } }) %} {% endfor %} {{ result }} - name: 打印结果 debug: var: target_dict
逻辑说明:
- 初始化空字典
result - 遍历
output2.results中的每一项,以每项的item值(id1/id2/id3)作为新字典的键 - 从每项的
msg.json中提取指定的key1和key3,作为对应键的子字典内容 - 最终将组装好的字典赋值给
target_dict
方法二:管道过滤链(简洁版)
用Ansible的过滤链一行完成结构重组,适合习惯管道语法的场景:
- name: 生成目标结构字典(简洁版) set_fact: target_dict: "{{ dict( output2.results | map('extract', ['item']) | zip( output2.results | map('extract', ['msg', 'json']) | map('dict2items') | selectattr('key', 'in', ['key1', 'key3']) | map('items2dict') ) ) }}" - name: 打印结果 debug: var: target_dict
逻辑说明:
output2.results | map('extract', ['item']):提取所有结果中的id值,作为新字典的键列表output2.results | map('extract', ['msg', 'json']):提取每个结果的原始json字典| map('dict2items') | selectattr('key', 'in', ['key1', 'key3']) | map('items2dict'):将json字典转为键值对列表,筛选出指定key后再转回字典,得到值列表dict(keys | zip(values)):将键列表和值列表组合成最终的目标字典
内容的提问来源于stack exchange,提问作者LJS
相关产品推荐
相关产品推荐

