Ansible循环中获取子元素下一个值以填充模板字段的方法问询
解决Ansible中Filter循环的配对问题
咱们直接来搞定这个需求:你需要遍历每个公司的filters列表,把当前filter和下一个filter配对,生成match_send=当前项 else_send=下一项的格式。直接用subelements没法实现相邻元素的配对逻辑,得换个思路处理数据。
方法一:先预处理数据(推荐,逻辑更清晰)
先在Playbook里给每个公司生成filter的配对列表,之后再遍历渲染:
- 用
set_fact预处理你的companies变量,给每个公司添加filter_pairs字段,里面是(当前filter, 下一个filter)的元组列表:
- name: 预处理公司的filter配对数据 set_fact: companies_with_pairs: >- {{ companies_with_pairs | default([]) + [ item | combine({'filter_pairs': item.filters | zip(item.filters[1:]) | list}) ] }} loop: "{{ companies }}" loop_control: label: "{{ item.name }}" # 只显示公司名称,让输出更整洁
这里的核心逻辑是item.filters | zip(item.filters[1:]):
item.filters[1:]会取出当前公司filters列表从第二个元素开始的子列表zip会把原列表和这个子列表一一配对,比如原列表是[A,B,C],配对后就是[(A,B), (B,C)]
- 之后在模板里遍历处理好的数据:
{% for company in companies_with_pairs %} # 处理 {{ company.name }} 的filter配对 {% for pair in company.filter_pairs %} match_send={{ pair.0.name }} else_send={{ pair.1.name }} # 如果需要用regex字段,就换成 pair.0.regex 和 pair.1.regex {% endfor %} {% endfor %}
方法二:直接在模板内处理(无需额外预处理)
如果不想修改原变量,也可以直接在Jinja2模板里通过索引实现配对:
{% for company in companies %} # 处理 {{ company.name }} 的filter {% set filters = company.filters %} {% for idx in range(filters | length - 1) %} # 只循环到倒数第二个元素,保证有下一个元素可以配对 match_send={{ filters[idx].name }} else_send={{ filters[idx+1].name }} {% endfor %} {% endfor %}
这里用range(filters | length - 1)限制循环次数,比如filters有2个元素,循环1次;有3个元素,循环2次,正好覆盖所有相邻配对。
边界情况说明
如果某个公司的filters列表只有1个元素,两种方法都不会生成任何配对(因为没有下一个元素可以作为else_send),这符合逻辑。
内容的提问来源于stack exchange,提问作者clmnt_sg
相关产品推荐
相关产品推荐

