我正在尝试从打印到 stdout 的 SQL 命令的结果中提取值。
first second
29494060 23004496
29774383 22979864
我想将其解析为如下所示的数据结构
[
{ first: 29494060, second: 23004496 },
{ first: 29774383, second: 22979864 }
]
这样我就可以访问每条记录的值,例如{{ item.first }}
和{{ item.second }}
.
我已经能够通过创建一个对象文字来提取单个记录,其中包含使用regex_replace
过滤器提取的值。
- set_fact:
items: { first: "{{ item | regex_replace('\s*?(\d+)\s*?(\d+)', '\1') }}", second: "{{ item | regex_replace('\s*?(\d+)\s*?(\d+)', '\2') }}" }
loop: '{{ command_out.stdout_lines }}'
这只会保留结果的最后一行。我无法为每个结果创建一个列表。由于嵌套的 Jinja 模板,我无法像items: "{{ items | default([]) + [{…}] }}"
那样使用列表串联。
如何将打印的数据表提取到对象列表中?
创建密钥。例如
- set_fact:
keys: "{{ command_out.stdout_lines[0].split() }}"
- debug:
var: keys
给
"keys": [
"first",
"second"
]
然后将由过滤器字典和 zip 创建的词典添加到列表中sql_list
- set_fact:
sql_list: "{{ sql_list|default([]) +
[dict(keys|zip(item.split()))] }}"
loop: "{{ command_out.stdout_lines[1:] }}"
- debug:
var: sql_list
给
"sql_list": [
{
"first": "29494060",
"second": "23004496"
},
{
"first": "29774383",
"second": "22979864"
}
]
自定义插件简化的任务给出了相同的结果
- set_fact:
sql_list: "{{ command_out.stdout_lines[1:]|
map('string_split')|
map('list_dict_zip_rev', keys)|
list }}"
$ cat filter_plugins/string_filters.py
def string_split(s, *i):
if len(i) == 0:
return s.split()
elif len(i) == 1:
return s.split(i[0])
else:
return s.split(i[0], i[1])
def list_dict_zip_rev(l,k):
return dict((y,x) for x,y in zip(l,k))
class FilterModule(object):
''' Ansible filters.'''
def filters(self):
return {
'list_dict_zip_rev' : list_dict_zip_rev,
'string_split' : string_split
}