是否可以使用 Ansible / Jinja2 中的格式化字符串将列表/字典列表转换为字符串列表?
我知道我可以做类似的事情:
{{["First: %d", "Second: %d"] | map("format", 1) | join(", ") }}
Run Code Online (Sandbox Code Playgroud)
要得到First: 1, Second 1。
是否可以做类似的事情
{{[[1, 1], [2, 2]] | map("format", "Num %d, %d") | join(", ") }}
Run Code Online (Sandbox Code Playgroud)
并导致Num 1, 1, Num 2, 2?
- debug:
msg: "{{ ['v1 %s', 'v2 %s']|map('format', 'XYZ')|list }}"
Run Code Online (Sandbox Code Playgroud)
给出
msg:
- v1 XYZ
- v2 XYZ
Run Code Online (Sandbox Code Playgroud)
_list: [[1, 1], [2, 2]]
Run Code Online (Sandbox Code Playgroud)
下面的表达式
result: "{{ _list|
map('join', ',')|
map('regex_replace', _regex, _replace)|
join(', ') }}"
_regex: '^(.*),(.*)$'
_replace: 'Num \1, \2'
Run Code Online (Sandbox Code Playgroud)
给出
result: Num 1, 1, Num 2, 2
Run Code Online (Sandbox Code Playgroud)
result: "{{ ['Num']|
product(_list|map('join', ', '))|
map('join', ' ')|
join(', ') }}"
Run Code Online (Sandbox Code Playgroud)
result: |-
{% for i in _list %}
Num {{ i|join(', ') }}{% if not loop.last %}, {% endif %}
{%- endfor %}
Run Code Online (Sandbox Code Playgroud)
用于测试的完整剧本示例
- hosts: localhost
vars:
_list: [[1, 1], [2, 2]]
result1: "{{ ['Num']|
product(_list|map('join', ', '))|
map('join', ' ')|
join(', ') }}"
result2: "{{ _list|
map('join', ',')|
map('regex_replace', _regex, _replace)|
join(', ') }}"
_regex: '^(.*),(.*)$'
_replace: 'Num \1, \2'
result3: |-
{% for i in _list %}
Num {{ i|join(', ') }}{% if not loop.last %}, {% endif %}
{%- endfor %}
tasks:
- debug:
msg: "{{ ['v1 %s', 'v2 %s']|map('format', 'XYZ')|list }}"
- debug:
var: result1
- debug:
var: result2
- debug:
var: result3
- assert:
that:
- result1 == 'Num 1, 1, Num 2, 2'
- result2 == 'Num 1, 1, Num 2, 2'
- result3 == 'Num 1, 1, Num 2, 2'
Run Code Online (Sandbox Code Playgroud)
对于核心format过滤器来说这是不可能的。但如果你愿意写几行Python,你可以使用自定义过滤器轻松解决这个问题。我选择了最简单的演示,您可能必须强化代码并修复边缘情况才能在现实生活中使用。您可能想查看插件开发文档以获取更多信息。
对于本示例,我将把自定义文件保存在filter_plugins与我的测试 playbook 相邻的目录中。如果您想在不同的项目之间共享,您可以将其保存在集合或角色中。
在filter_plugins/my_format_filters.py
\ndef reverse_format(param_list, format_string):\n """format format_sting using elements in param_list"""\n return format_string % tuple(param_list)\n\n\nclass FilterModule(object):\n """my format filters."""\n\n def filters(self):\n """Return the filter list."""\n return {\n \'reverse_format\': reverse_format\n }\nRun Code Online (Sandbox Code Playgroud)\n然后是以下示例剧本:
\n---\n- name: custom filter demo\n hosts: localhost\n gather_facts: false\n\n tasks:\n - name: map custom reverse_format filter\n debug:\n msg: \'{{ item.replacements | map("reverse_format", item.format) | join(", ") }}\'\n loop:\n - replacements:\n - [1, 1]\n - [2, 2]\n format: "Num %d, %d"\n - replacements:\n - [\'Jack\', \'John\', 12]\n - [\'Mary\', \'Alicia\', 34]\n format: "%s owes %s %d\xe2\x82\xac"\nRun Code Online (Sandbox Code Playgroud)\n给出:
\nPLAY [custom filter demo] **************************************************************************************************************************************************************************************************************\n\nTASK [map custom reverse_format filter] ************************************************************************************************************************************************************************************************\nok: [localhost] => (item={\'replacements\': [[1, 1], [2, 2]], \'format\': \'Num %d, %d\'}) => {\n "msg": "Num 1, 1, Num 2, 2"\n}\nok: [localhost] => (item={\'replacements\': [[\'Jack\', \'John\', 12], [\'Mary\', \'Alicia\', 34]], \'format\': \'%s owes %s %d\xe2\x82\xac\'}) => {\n "msg": "Jack owes John 12\xe2\x82\xac, Mary owes Alicia 34\xe2\x82\xac"\n}\n\nPLAY RECAP *****************************************************************************************************************************************************************************************************************************\nlocalhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
3084 次 |
| 最近记录: |