我有两个单独的列表。第一个是具有基本参数的列表(base_list),第二个是具有特定支架的参数的列表(dev_list)。
"base_list": [
{
"name": "kibana",
"path": "kibana/conf/kibana.xml",
"src": "/Users/ansible/inventories/_base/group_vars/kibana/conf/kibana.xml"
},
{
"name": "logstash",
"path": "logstash/conf/logstash.yml",
"src": "/Users/ansible/inventories/_base/group_vars/logstash/conf/logstash.yml"
},
{
"name": "grafana",
"path": "grafana/conf/grafana.json",
"src": "/Users/ansible/inventories/_base/group_vars/grafana/conf/grafana.json"
},
{
"name": "grafana",
"path": "grafana/conf/nginx.json",
"src": "/Users/ansible/inventories/_base/group_vars/grafana/conf/nginx.json"
},
{
"name": "grafana",
"path": "grafana/conf/config.json",
"src": "/Users/ansible/inventories/_base/group_vars/grafana/conf/config.json"
},
]
"dev_list": [
{
"name": "kibana",
"path": "kibana/conf/kibana.xml",
"src": "/Users/ansible/inventories/dev-st/group_vars/kibana/conf/kibana.xml"
},
{
"name": "logstash",
"path": "logstash/conf/jvm.options",
"src": "/Users/ansible/inventories/dev-st/group_vars/logstash/conf/jvm.options"
}
]
我的目标是将这两个列表组合在一起,以获得一个item.name和几个item.path和item.src。看起来像这样的路径:
"end_list": [
{
"name": "kibana",
"path": "kibana/conf/kibana.xml",
"src": "/Users/ansible/inventories/dev-st/group_vars/kibana/conf/kibana.xml"
},
{
"name": "logstash",
"path": [
"logstash/conf/logstash.yml",
"logstash/conf/jvm.options"
],
"src": [
"/Users/ansible/inventories/_base/group_vars/logstash/conf/logstash.yml",
"/Users/ansible/inventories/dev-st/group_vars/logstash/conf/jvm.options"
]
},
{
"name": "grafana",
"path": [
"grafana/conf/grafana.json",
"grafana/conf/nginx.json",
"grafana/conf/config.json"
]
"src": [
"/Users/ansible/inventories/_base/group_vars/grafana/conf/grafana.json",
"/Users/ansible/inventories/_base/group_vars/grafana/conf/nginx.json",
"/Users/ansible/inventories/_base/group_vars/grafana/conf/config.json"
]
},
]
什么是最好的方法?
答案 0 :(得分:1)
使用自定义Python过滤器可能会更容易,但这是使用Ansible内置过滤器的解决方案:
---
- hosts: localhost
gather_facts: false
vars:
"base_list": [
{
"name": "kibana",
"path": "kibana/conf/kibana.xml",
"src": "/Users/ansible/inventories/_base/group_vars/kibana/conf/kibana.xml"
},
{
"name": "logstash",
"path": "logstash/conf/logstash.yml",
"src": "/Users/ansible/inventories/_base/group_vars/logstash/conf/logstash.yml"
},
{
"name": "grafana",
"path": "grafana/conf/grafana.json",
"src": "/Users/ansible/inventories/_base/group_vars/grafana/conf/grafana.json"
},
]
"dev_list": [
{
"name": "kibana",
"path": "kibana/conf/kibana.xml",
"src": "/Users/ansible/inventories/dev-st/group_vars/kibana/conf/kibana.xml"
},
{
"name": "logstash",
"path": "logstash/conf/jvm.options",
"src": "/Users/ansible/inventories/dev-st/group_vars/logstash/conf/jvm.options"
}
]
tasks:
- set_fact:
end_list: >-
{{ end_list|default([]) + [
{
'name': item.0.name,
'path': item.1.path|ternary([item.0.path, item.1.path], item.0.path),
'src': item.1.src|ternary([item.0.src, item.1.src], item.1.src)
}
]}}
loop: >-
{{ base_list|zip_longest(dev_list,
fillvalue={'path': false, 'src': false})|list }}
- debug:
var: end_list
放在一起有点棘手,所以我将尝试描述各个部分:
循环使用zip_longest过滤器。给定列表list1=[1, 2, 3]
和list2=[11, 12]
,list1|zip_longest(list2)
将产生[[1,11], [2,12], [3,None]]
(即默认情况下,zip_longest
将使用None
作为填充值如果一个列表比另一个列表短)。通过设置fillvalue
参数,我们可以使用None
以外的其他值。在这种情况下...
loop: >-
{{ base_list|zip_longest(dev_list,
fillvalue={'path': false, 'src': false})|list }}
...我们正在将填充值设置为具有path
和src
的存根值的字典,因为这使表达式的其余部分更容易。
解决方案的重点当然是set_fact
操作,其简化形式如下:
end_list: "{{ end_list|default([]) + [{...a dictionary...}] }}"
换句话说,对于loop
的每次迭代,这都会向end_list
附加新的字典。
我们这样创建字典:
{
'name': item.0.name,
'path': item.1.path|ternary([item.0.path, item.1.path], item.0.path),
'src': item.1.src|ternary([item.0.src, item.1.src], item.1.src)
}
我们在这里使用ternary
过滤器,该过滤器将其输入评估为布尔值;如果为true
,则选择第一个参数,否则选择第二个。这里我们利用传递给fillvalue
过滤器的zip_longest
的优势:如果dev_list
短于base_list
,我们将有一些{{1 }}和item.1.path
为item.1.src
,从而使三元过滤器选择第二个值(false
或item.0.path
)。在其他情况下,我们通过组合item.1.src
和base_list
中的每个值来构建列表。
运行此剧本的结果如下:
dev_list
请让我知道是否有帮助,以及是否找到了所需的数据结构。由于您的示例ok: [localhost] => {
"end_list": [
{
"name": "kibana",
"path": [
"kibana/conf/kibana.xml",
"kibana/conf/kibana.xml"
],
"src": [
"/Users/ansible/inventories/_base/group_vars/kibana/conf/kibana.xml",
"/Users/ansible/inventories/dev-st/group_vars/kibana/conf/kibana.xml"
]
},
{
"name": "logstash",
"path": [
"logstash/conf/logstash.yml",
"logstash/conf/jvm.options"
],
"src": [
"/Users/ansible/inventories/_base/group_vars/logstash/conf/logstash.yml",
"/Users/ansible/inventories/dev-st/group_vars/logstash/conf/jvm.options"
]
},
{
"name": "grafana",
"path": "grafana/conf/grafana.json",
"src": false
}
]
}
包含无效的语法,因此我不得不做一些假设,所以我猜测了您想要的是什么。
答案 1 :(得分:0)
假设您具有格式正确的json并且这些是根对象上的属性,则jq非常适合此操作。按名称对数组的内容进行分组,然后生成适当的结果对象。
date = "12/01/2019"
day = 01
month = 12
year = 2019
$ jq '{
end_combine: (
.base_list + .dev_list
| group_by(.name)
| map({ name: .[0].name, path: map(.path), src: map(.src) })
)
}' input.json