如何在Ansible中遍历YAML文件并打印所有键的完整路径与值?
问题描述
编写Ansible Playbook遍历input.yaml文件,要求打印每个键的完整路径及其对应值。当前代码能正常处理顶层键name、surname,但处理嵌套的address相关键时失败,报错:'dict object' has no attribute 'address.city'。
示例文件
input.yaml
name: Alice surname: Smith address: city: New York zipcode: 10001 contact: email: alice@example.com phone: home: 555-1234 work: 555-5678
错误的Playbook(list.yaml)
- name: Print key-value pairs hosts: localhost vars_files: - input.yaml tasks: - name: Print top-level keys debug: msg: "{{ item.key }}: {{ my_vars[item.key] }}" loop: "{{ my_vars | dict2items }}" vars: my_vars: "{{ vars | dict2items | selectattr('key', 'in', ['name', 'surname', 'address', 'contact']) | items2dict }}"
解决方案
要处理嵌套字典,需要递归遍历所有层级的键值对,而非仅处理顶层。以下是两种可行实现方法:
方法1:使用递归Jinja2过滤器
通过自定义Jinja2递归过滤器生成完整路径与值的列表,再遍历打印:
- name: Recursively print all key-value paths hosts: localhost vars_files: - input.yaml tasks: - name: Generate recursive key-value list set_fact: recursive_items: > {%- set output = [] -%} {%- macro recurse(d, path='') -%} {%- for k, v in d.items() -%} {%- set current_path = path ~ k -%} {%- if v is mapping -%} {{ recurse(v, current_path ~ '.') }} {%- else -%} {{ output.append({'path': current_path, 'value': v}) }} {%- endif -%} {%- endfor -%} {%- endmacro -%} {%- set _ = recurse(my_vars) -%} {{ output }} vars: my_vars: "{{ vars | dict2items | selectattr('key', 'in', ['name', 'surname', 'address', 'contact']) | items2dict }}" - name: Print all paths and values debug: msg: "{{ item.path }}: {{ item.value }}" loop: "{{ recursive_items }}"
方法2:使用递归任务调用
通过include_tasks实现递归遍历,适合复杂嵌套场景:
- 创建
recurse.yaml任务文件:
- name: Recurse into nested dict include_tasks: recurse.yaml loop: "{{ current_dict | dict2items }}" vars: current_path: "{{ current_path ~ item.key ~ '.' }}" current_dict: "{{ item.value }}" when: item.value is mapping - name: Print leaf node key-value debug: msg: "{{ current_path ~ item.key }}: {{ item.value }}" loop: "{{ current_dict | dict2items }}" when: item.value is not mapping
- 主Playbook(list.yaml):
- name: Recursively print key-value paths hosts: localhost vars_files: - input.yaml tasks: - name: Start recursive traversal include_tasks: recurse.yaml loop: "{{ my_vars | dict2items }}" vars: current_path: "" current_dict: "{{ item.value }}" vars: my_vars: "{{ vars | dict2items | selectattr('key', 'in', ['name', 'surname', 'address', 'contact']) | items2dict }}"
说明
两种方法核心都是通过is mapping判断是否为嵌套字典,递归遍历直到叶节点,同时动态拼接完整路径,避免硬编码嵌套路径导致的报错。
内容的提问来源于stack exchange,提问作者Arjun
相关产品推荐
相关产品推荐

