Ansible中map(regex_replace)后列表对比及重复项排查
问题解答
1. 标准化list3以实现正确的difference对比
问题原因
原代码直接对整个字典执行map('ansible.builtin.regex_replace'),导致list3的元素变成了字符串类型,而list2的元素是字典类型。difference过滤器无法在不同类型的元素间做有效对比,因此得不到预期的差异结果。
解决方案
仅针对list1中每个字典的name字段做正则替换,保持元素的字典结构不变。可以通过列表推导式结合combine过滤器实现:
- name: Debug hosts: "localhost" gather_facts: no connection: local vars: list1: - {name: aBC_SOMEITEM-A01_dEF, type: random, policy: one} - {name: aBC_SOMEITEM-A02_dEF, type: random, policy: two} - {name: aBC_SOMEITEM-A03_dEF, type: random, policy: three} list2: - {name: "SOMEITEM-A01", type: "random", policy: "one"} - {name: "SOMEITEM-A02", type: "random", policy: "two"} - {name: "SOMEITEM-A03", type: "random", policy: "three"} - {name: "SOMEITEM-A03", type: "random", policy: "three"} - {name: "SOMEITEM-A04", type: "random", policy: "four"} # 标准化list3:仅清洗name字段,保留字典结构 list3: >- {% set normalized_list = [] %} {% for item in list1 %} {% set cleaned_name = item.name | regex_replace('aBC_|_dEF', '') %} {% set _ = normalized_list.append(item | combine({'name': cleaned_name})) %} {% endfor %} {{ normalized_list }} tasks: - debug: msg: "{{ list2 | difference(list3) | to_yaml(default_flow_style=none) }}"
执行结果
此时difference可正确对比两个字典列表,输出预期差异项:
- {name: SOMEITEM-A04, policy: four, type: random}
2. 找出list2中的重复字典项
基础解决方案
利用groupby过滤器将完全相同的字典分组(以字典的JSON字符串作为分组键),筛选出分组长度大于1的项即为重复项:
tasks: - name: 提取list2中的重复项 set_fact: duplicate_items: >- {% set grouped_items = list2 | groupby('to_json') %} {% set duplicates = [] %} {% for key, items in grouped_items %} {% if items | length > 1 %} {% set _ = duplicates.append(items[0]) %} {% endif %} {% endfor %} {{ duplicates }} - debug: msg: "{{ duplicate_items | to_yaml(default_flow_style=none) }}"
执行结果
输出list2中的重复字典:
- {name: "SOMEITEM-A03", policy: "three", type: "random"}
大数据集优化
如果处理超大列表,模板循环效率较低,可编写自定义过滤器插件:
- 在Ansible的过滤器目录(如
filter_plugins/)创建list_utils.py:
def find_duplicates(input_list): seen = {} duplicates = [] for item in input_list: # 将字典转为可哈希的有序元组,保证相同结构的字典能匹配 key = tuple(sorted(item.items())) if key in seen: if seen[key] == 1: duplicates.append(item) seen[key] += 1 else: seen[key] = 1 return duplicates class FilterModule(object): def filters(self): return { 'find_duplicates': find_duplicates }
- 在Playbook中调用自定义过滤器:
tasks: - debug: msg: "{{ list2 | find_duplicates | to_yaml(default_flow_style=none) }}"
内容的提问来源于stack exchange,提问作者honeybeeham
相关产品推荐
相关产品推荐

