Ansible单列表匹配相同tunnel值后合并对应custip值的实现方法
解决方案
你可以直接使用Ansible内置的Jinja2 groupby 过滤器实现按指定字段分组,再提取合并对应字段,无需额外依赖。
完整可运行Playbook示例
--- - name: 合并同tunnel的custip字段 hosts: localhost gather_facts: false vars: # 替换为你实际获取的原始列表 original_list: - custip: "192.168.10.0/24" tunnel: "tunnel.5" - custip: "192.168.20.0/24" tunnel: "tunnel.5" - custip: "1.1.1.1/32" tunnel: "tunnel.10" - custip: "2.2.2.0/24" tunnel: "tunnel.11" - custip: "3.3.3.0/24" tunnel: "tunnel.11" tasks: - name: 按tunnel分组并合并custip ansible.builtin.set_fact: merged_list: >- {{ merged_list | default([]) + [ { 'tunnel': item[0], 'custip': item[1] | map(attribute='custip') | list } ] }} loop: "{{ original_list | groupby('tunnel') }}" - name: 打印合并后的结果 ansible.builtin.debug: var: merged_list
运行输出
和你期望的结果完全一致:
TASK [打印合并后的结果] **************************************************************** ok: [localhost] => { "merged_list": [ { "custip": [ "192.168.10.0/24", "192.168.20.0/24" ], "tunnel": "tunnel.5" }, { "custip": [ "1.1.1.1/32" ], "tunnel": "tunnel.10" }, { "custip": [ "2.2.2.0/24", "3.3.3.0/24" ], "tunnel": "tunnel.11" } ] }
核心逻辑说明
original_list | groupby('tunnel'):将原始列表按tunnel字段的值分组,返回二元组列表,每个二元组第一个元素是分组的tunnel值,第二个元素是该分组下所有原始元素的列表item[1] | map(attribute='custip') | list:提取当前分组下所有元素的custip字段,转换为列表- 循环遍历所有分组,拼接成符合要求的结构体,兼容性好,支持所有Ansible 2.5+版本
如果你使用的是Ansible 2.10+版本,且安装了community.general集合,也可以用单行表达式实现,无需显式循环:
- name: 单行表达式生成合并结果 ansible.builtin.set_fact: merged_list: "{{ original_list | groupby('tunnel') | map('json_query', '{tunnel: [0].tunnel, custip: [*].custip}') | list }}"
内容的提问来源于stack exchange,提问作者nauto
相关产品推荐
相关产品推荐

