格式化 Ansible/Jinja2 中的项目列表
Formatting a list of items in Ansible/Jinja2
是否可以使用 Ansible / Jinja2 中的格式化字符串将 lists/dicts 列表转换为字符串列表?
我知道我可以做类似的事情:
{{["First: %d", "Second: %d"] | map("format", 1) | join(", ") }}
得到First: 1, Second 1
.
是否可以做类似的事情
{{[[1, 1], [2, 2]] | map("format", "Num %d, %d") | join(", ") }}
并导致 Num 1, 1, Num 2, 2
?
没有。这是不可能的。 format的参数是相反的,例如
- debug:
msg: "{{ ['v1 %s', 'v2 %s']|map('format', 'XYZ')|list }}"
给予
msg:
- v1 XYZ
- v2 XYZ
相反,可以映射 join 和 regex_replace,例如
- debug:
msg: "{{ _list|
map('join', ',')|
map('regex_replace', _regex, _replace)|
join(', ') }}"
vars:
_list: [[1,1],[2,2]]
_regex: '^(.*),(.*)$'
_replace: 'Num , '
做这份工作
msg: Num 1, 1, Num 2, 2
使用核心 format
过滤器是不可能的。但是如果你愿意写几行python,用自定义过滤器就可以轻松解决这个问题。我去了最简单的演示,您可能必须强化代码并修复边缘情况以供实际使用。您可能想查看 plugin development documentation 了解更多信息。
对于此示例,如果您想在不同项目之间共享,我会将自定义文件保存在 filter_plugins
directory adjacent to my test playbook. You can save it in a collection or a role 中。
在filter_plugins/my_format_filters.py
def reverse_format(param_list, format_string):
"""format format_sting using elements in param_list"""
return format_string % tuple(param_list)
class FilterModule(object):
"""my format filters."""
def filters(self):
"""Return the filter list."""
return {
'reverse_format': reverse_format
}
然后是以下示例剧本:
---
- name: custom filter demo
hosts: localhost
gather_facts: false
tasks:
- name: map custom reverse_format filter
debug:
msg: '{{ item.replacements | map("reverse_format", item.format) | join(", ") }}'
loop:
- replacements:
- [1, 1]
- [2, 2]
format: "Num %d, %d"
- replacements:
- ['Jack', 'John', 12]
- ['Mary', 'Alicia', 34]
format: "%s owes %s %d€"
给出:
PLAY [custom filter demo] **************************************************************************************************************************************************************************************************************
TASK [map custom reverse_format filter] ************************************************************************************************************************************************************************************************
ok: [localhost] => (item={'replacements': [[1, 1], [2, 2]], 'format': 'Num %d, %d'}) => {
"msg": "Num 1, 1, Num 2, 2"
}
ok: [localhost] => (item={'replacements': [['Jack', 'John', 12], ['Mary', 'Alicia', 34]], 'format': '%s owes %s %d€'}) => {
"msg": "Jack owes John 12€, Mary owes Alicia 34€"
}
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
在已经接受的答案的基础上,这里有一个版本也支持 dicts/objects:
的馈送列表
class FilterModule(object):
"""my format filters."""
def filters(self):
"""Return the filter list."""
return {
'reverse_format': self.reverse_format
}
def reverse_format(self, value, format_string):
"""format format_sting using elements in param_list"""
return format_string.format(**value)
用法示例:
{{ hostvars.values() |
map('reverse_format', 'This is inventory host {inventory_hostname}!' |
join('\n') }}
是否可以使用 Ansible / Jinja2 中的格式化字符串将 lists/dicts 列表转换为字符串列表?
我知道我可以做类似的事情:
{{["First: %d", "Second: %d"] | map("format", 1) | join(", ") }}
得到First: 1, Second 1
.
是否可以做类似的事情
{{[[1, 1], [2, 2]] | map("format", "Num %d, %d") | join(", ") }}
并导致 Num 1, 1, Num 2, 2
?
没有。这是不可能的。 format的参数是相反的,例如
- debug:
msg: "{{ ['v1 %s', 'v2 %s']|map('format', 'XYZ')|list }}"
给予
msg:
- v1 XYZ
- v2 XYZ
相反,可以映射 join 和 regex_replace,例如
- debug:
msg: "{{ _list|
map('join', ',')|
map('regex_replace', _regex, _replace)|
join(', ') }}"
vars:
_list: [[1,1],[2,2]]
_regex: '^(.*),(.*)$'
_replace: 'Num , '
做这份工作
msg: Num 1, 1, Num 2, 2
使用核心 format
过滤器是不可能的。但是如果你愿意写几行python,用自定义过滤器就可以轻松解决这个问题。我去了最简单的演示,您可能必须强化代码并修复边缘情况以供实际使用。您可能想查看 plugin development documentation 了解更多信息。
对于此示例,如果您想在不同项目之间共享,我会将自定义文件保存在 filter_plugins
directory adjacent to my test playbook. You can save it in a collection or a role 中。
在filter_plugins/my_format_filters.py
def reverse_format(param_list, format_string):
"""format format_sting using elements in param_list"""
return format_string % tuple(param_list)
class FilterModule(object):
"""my format filters."""
def filters(self):
"""Return the filter list."""
return {
'reverse_format': reverse_format
}
然后是以下示例剧本:
---
- name: custom filter demo
hosts: localhost
gather_facts: false
tasks:
- name: map custom reverse_format filter
debug:
msg: '{{ item.replacements | map("reverse_format", item.format) | join(", ") }}'
loop:
- replacements:
- [1, 1]
- [2, 2]
format: "Num %d, %d"
- replacements:
- ['Jack', 'John', 12]
- ['Mary', 'Alicia', 34]
format: "%s owes %s %d€"
给出:
PLAY [custom filter demo] **************************************************************************************************************************************************************************************************************
TASK [map custom reverse_format filter] ************************************************************************************************************************************************************************************************
ok: [localhost] => (item={'replacements': [[1, 1], [2, 2]], 'format': 'Num %d, %d'}) => {
"msg": "Num 1, 1, Num 2, 2"
}
ok: [localhost] => (item={'replacements': [['Jack', 'John', 12], ['Mary', 'Alicia', 34]], 'format': '%s owes %s %d€'}) => {
"msg": "Jack owes John 12€, Mary owes Alicia 34€"
}
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
在已经接受的答案的基础上,这里有一个版本也支持 dicts/objects:
的馈送列表class FilterModule(object):
"""my format filters."""
def filters(self):
"""Return the filter list."""
return {
'reverse_format': self.reverse_format
}
def reverse_format(self, value, format_string):
"""format format_sting using elements in param_list"""
return format_string.format(**value)
用法示例:
{{ hostvars.values() |
map('reverse_format', 'This is inventory host {inventory_hostname}!' |
join('\n') }}