如何为dict2items循环输出选择性追加字符串?
问题描述
我有如下嵌套字典结构:
machines: dev1: disks: 4 user: fred NICs: eth0 dev2: disks: 4 user: joe NICs: eth0
通过循环和dict2items过滤器可以生成如下输出:
- debug: msg: "something {{item.value.user}}" loop: "{{ machines | dict2items }}"
输出结果:
ok: => msg: something fred ok: => msg: something joe
现在需要动态修改特定字典值,比如给dev1的user追加-somebody后缀(输出变为something fred-somebody),而dev2的user保持不变,想了解能否通过循环过滤器实现,或者有其他解决思路。
解决方案
方法1:模板内直接做条件判断
最直接的方式是在msg模板中,根据机器的键名(item.key)做条件判断,动态拼接后缀:
- debug: msg: "something {{ item.value.user }}{% if item.key == 'dev1' %}-somebody{% endif %}" loop: "{{ machines | dict2items }}"
执行后dev1的输出会自动追加指定后缀,其他机器保持原有值不变。
方法2:用map过滤器预处理数据
如果需要复用修改逻辑,可以用map过滤器结合combine,先批量处理字典列表再循环:
- debug: msg: "something {{ item.user }}" loop: >- {{ machines | dict2items | map('combine', {'value': {'user': item.value.user + ('-somebody' if item.key == 'dev1' else '')}}) | map(attribute='value') }}
这种写法适合需要同时处理多个字段的场景,但相对复杂。
方法3:提前修改原始字典变量
如果后续步骤也要用到修改后的字典数据,可以先用set_fact更新原始变量,再循环输出:
- set_fact: machines: "{{ machines | combine({'dev1': {'user': machines.dev1.user + '-somebody'}}, recursive=True) }}" - debug: msg: "something {{ item.value.user }}" loop: "{{ machines | dict2items }}"
此方法会永久修改machines变量的值,适合全流程需要使用修改后数据的场景。
方法4:自定义过滤器(进阶复用)
如果需要多次使用“根据键名修改字段值”的逻辑,可以自定义Ansible过滤器:
- 在项目根目录创建
filter_plugins/custom_filters.py文件:
def add_suffix_to_key(data, target_key, suffix): result = {} for k, v in data.items(): if k == target_key and 'user' in v: updated_v = v.copy() updated_v['user'] = v['user'] + suffix result[k] = updated_v else: result[k] = v return result class FilterModule(object): def filters(self): return { 'add_suffix_to_key': add_suffix_to_key }
- 在Playbook中调用自定义过滤器:
- debug: msg: "something {{ item.value.user }}" loop: "{{ machines | add_suffix_to_key('dev1', '-somebody') | dict2items }}"
这种方式代码更简洁,适合复杂且需要重复使用的场景。
内容的提问来源于stack exchange,提问作者Adam Gold
相关产品推荐
相关产品推荐

