如何在Ansible中遍历字典提取特定字段并生成完整包名列表?
问题:如何在Ansible中生成完整包名列表?
背景信息
我通过ansible.package_facts过滤得到仅包含特定版本包的字典filtered_ansible_packages,示例如下:
"filtered_ansible_packages": { "cool_package1": [ { "arch": "noarch", "epoch": "null", "name": "cool_package1", "release": "el7", "version": "1.2.6" } ], "cool_package2": [ { "arch": "noarch", "epoch": "null", "name": "cool_package2", "release": "el7", "version": "1.4.7" } ] }
UPDATE:以下是filtered_ansible_packages的定义方式:
# 另一个任务 set_fact: filtered_ansible_packages: "{{ filtered_ansible_packages | default({}) | combine(new_item | items2dict) }}" with_dict: "{{ ansible_facts.packages }}" loop_control: label: "{{ item.key }}" vars: el7_release: "{{ item.value | selectattr('release', 'search', 'el7') | list}}" new_item: - key: "{{ item.key }}" value: "{{ el7_releases}}" when: el7_releases | list | length
需求
遍历每个包,提取name、release、version和arch字段,拼接成格式为{name}.{version}.{release}.{arch}的完整包名字符串(例如cool_package1对应cool_package1.1.2.6.el7.noarch),并将这些完整包名存入full_package_name_list列表。同时想知道是否需要用dict2items将字典转为列表。
解决方案
不需要额外使用dict2items,直接通过Ansible的过滤器和循环就能实现,推荐两种实用方式:
方式一:循环拼接(新手友好)
通过循环逐个处理包数据,拼接字符串并追加到列表:
- name: 生成完整包名列表 set_fact: full_package_name_list: "{{ full_package_name_list | default([]) + [full_package_name] }}" loop: "{{ filtered_ansible_packages.values() | flatten }}" vars: full_package_name: "{{ item.name }}.{{ item.version }}.{{ item.release }}.{{ item.arch }}"
方式二:纯过滤器实现(简洁高效)
利用Ansible的过滤器链一次性生成列表,无需显式循环:
- name: 生成完整包名列表 set_fact: full_package_name_list: >- {{ filtered_ansible_packages.values() | flatten | map('format', '%s.%s.%s.%s') | map('extract', ['name', 'version', 'release', 'arch']) | list }}
关键说明
filtered_ansible_packages.values()取出字典中所有的包列表,flatten将嵌套的单元素列表转为一维列表,方便后续处理- 方式一逻辑直观,适合刚接触Ansible的用户理解
- 方式二用过滤器链实现,代码更简洁,执行效率更高
- 完全不需要
dict2items,因为我们只需要处理包数据本身,直接取字典值并扁平化就足够
内容的提问来源于stack exchange,提问作者murphman10
相关产品推荐
相关产品推荐

