如何从 Ansible 中以 table 分隔的宽度中提取值?
How do I extract values from a width delimited table in Ansible?
我正在尝试从打印到标准输出的 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([]) + [{…}] }}"
这样的列表连接。
如何将打印的 table 数据提取到对象列表中?
创建键。例如
- set_fact:
keys: "{{ command_out.stdout_lines[0].split() }}"
- debug:
var: keys
给予
"keys": [
"first",
"second"
]
然后将过滤器 dict and 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"
}
]
custom plugins 简化的任务给出相同的结果
- 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
}
我正在尝试从打印到标准输出的 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([]) + [{…}] }}"
这样的列表连接。
如何将打印的 table 数据提取到对象列表中?
创建键。例如
- set_fact:
keys: "{{ command_out.stdout_lines[0].split() }}"
- debug:
var: keys
给予
"keys": [
"first",
"second"
]
然后将过滤器 dict and 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"
}
]
custom plugins 简化的任务给出相同的结果
- 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
}