Python 在ansible中使用list和dict的嵌套循环
我在ansible中有两种类型的输入数据。 Firs是字符串列表:Python 在ansible中使用list和dict的嵌套循环,python,loops,ansible,conditional-statements,Python,Loops,Ansible,Conditional Statements,我在ansible中有两种类型的输入数据。 Firs是字符串列表: - '1.1.1.1' - '2.2.2.2' 第二个是口述清单 - {'name': 'obj1', 'addr': '1.1.1.1'} - {'name': 'objx', 'addr': 'x.x.x.x'} 我事先不知道第一个列表的项目是否在第二个列表的addr文件中。因此,我必须执行求值,为此,我必须使用嵌套循环。我需要循环第一个列表和第二个列表,然后执行条件检查第一个列表的item是否等于第二个列表的item.
- '1.1.1.1'
- '2.2.2.2'
第二个是口述清单
- {'name': 'obj1', 'addr': '1.1.1.1'}
- {'name': 'objx', 'addr': 'x.x.x.x'}
我事先不知道第一个列表的项目是否在第二个列表的addr文件中。因此,我必须执行求值,为此,我必须使用嵌套循环。我需要循环第一个列表和第二个列表,然后执行条件检查第一个列表的item是否等于第二个列表的item.addr。然而,我不知道如何在ansible条件下区分第一个列表的项目和第二个列表的项目
在python中,我将通过使用以下表达式实现类似的功能:
for add in my_list:
for obj in my_list2:
if add == obj['addr']:
new_list.append([obj])
在ansible中,应该是这样的:
- set_fact:
new_list: "{{ new_list }} + [ {'name': '{{ item_second_list.name }}', 'address': '{{ item_second_list.addr }}'} ]"
when: item_first_list == item_second_list.addr
with_list: first_list
with_list: second_list
您可以尝试使用with_嵌套 下面是一个示例..(不是工作代码,仅供参考) 参考: 输出:
ok: [localhost] => (item=[u'1.1.1.1', {u'name': u'obj1', u'addr': u'1.1.1.1'}]) => {
"ansible_facts": {
"new_list": " [] + {u'name': u'obj1', u'addr': u'1.1.1.1'} "
},
在YAML字典中有两个相同的键是错误的。换言之,您不能将
与_list
一起使用两次:它应该会生成一个错误,否则,除了最后一个错误以外的所有内容都将被忽略。在大多数情况下,Ansible不直接支持嵌套循环
看起来您想要生成一个包含在字典列表中的地址列表。也就是说,考虑到:
list1:
- 1.1.1.1
- 2.2.2.2
- 3.3.3.3
list2:
- {'name': 'obj1', 'addr': '1.1.1.1'}
- {'name': 'objx', 'addr': '2.2.2.2'}
您希望生成一个新列表:
list3:
- 1.1.1.1
- 2.2.2.2
在没有嵌套列表的情况下,我们可以通过询问list2
中的所有地址,然后仅选择list1中的:
---
- hosts: localhost
gather_facts: false
vars:
list1:
- 1.1.1.1
- 2.2.2.2
- 3.3.3.3
list2:
- name: obj1
addr: 1.1.1.1
- name: obj2
addr: 2.2.2.2
tasks:
- set_fact:
list3: "{{ (list3|default([])) + [item.addr] }}"
when: item.addr in list1
loop: "{{ list2 }}"
- debug:
var: list3
这将输出:
[...]
TASK [debug] *************************************************************************
ok: [localhost] => {
"list3": [
"1.1.1.1",
"2.2.2.2"
]
}
下面的剧本
vars:
my_list:
- '1.1.1.1'
- '2.2.2.2'
my_dict:
- {'name': 'obj1', 'addr': '1.1.1.1'}
- {'name': 'objx', 'addr': 'x.x.x.x'}
tasks:
- set_fact:
sel_list: "{{ sel_list|default([]) +
my_dict|
selectattr('addr', 'in', my_list)|
list }}"
- debug:
var: sel_list
给予
我认为这行不通:不能保证两个列表的长度相同。在链接中提供的文档示例中,列表的长度不同。测试并粘贴输出此解决方案对我非常有效。我想反之亦然,但这种结构是有道理的。我的意思是检查元素是否存在于列表中要比通过两个列表循环容易得多。非常感谢。这种方法同样有效。不过这是一个有点复杂的过滤器表达式。谢谢分享。是的。复杂性很明显my_dict | selectattr('addr','in',my_list)
。
[...]
TASK [debug] *************************************************************************
ok: [localhost] => {
"list3": [
"1.1.1.1",
"2.2.2.2"
]
}
vars:
my_list:
- '1.1.1.1'
- '2.2.2.2'
my_dict:
- {'name': 'obj1', 'addr': '1.1.1.1'}
- {'name': 'objx', 'addr': 'x.x.x.x'}
tasks:
- set_fact:
sel_list: "{{ sel_list|default([]) +
my_dict|
selectattr('addr', 'in', my_list)|
list }}"
- debug:
var: sel_list
"sel_list": [
{
"addr": "1.1.1.1",
"name": "obj1"
}
]