Jinja2:格式化+加入列表的项目

Jinja2: format + join the items of a list

play_hosts 是播放所有机器的列表。我想使用这些并使用 format() 之类的东西将它们重写为 rabbitmq@%s,然后将它们与 join() 之类的东西连接在一起。所以:

{{ play_hosts|format(???)|join(', ') }}

格式的所有示例都使用管道,其中输入是格式字符串而不是列表。有没有办法使用这些(或其他东西)来完成我想要的?输出应该类似于:

['rabbitmq@server1', 'rabbitmq@server2', rabbitmq@server3', ...]

jinja2 文档描述的格式如下:

format(value, *args, **kwargs)

对对象应用 python 字符串格式:

{{ "%s - %s"|format("Hello?", "Foo!") }}
-> Hello? - Foo!

所以它提供了三种输入,但没有在示例中描述这些输入,示例中显示了一种在管道中,另外两种通过 args 传入。是否有关键字 arg 来指定通过管道传输的字符串? python僧侣们请帮忙!

您可以创建自定义过滤器

# /usr/share/ansible/plugins/filter/format_list.py (check filter_plugins path in ansible.cfg)

def format_list(list_, pattern):
    return [pattern % s for s in list_]


class FilterModule(object):
    def filters(self):
        return {
            'format_list': format_list,
        }

并使用它

{{ play_hosts | format_list('rabbitmq@%s') }}

您不仅可以 join ,,还可以加上前缀。现在这不是非常 pythonic 或复杂,而是一个非常简单的工作解决方案:

[rabbitmq@{{ play_hosts | join(', rabbitmq@') }}]

在ansible中你可以使用regex_replace过滤器:

{{ play_hosts | map('regex_replace', '^(.*)$', 'rabbitmq@\1') | list }}

我相信另一种方法是使用 joiner 全局函数,您可以在 http://jinja.pocoo.org/docs/2.9/templates/#list-of-global-functions:

中阅读

A joiner is passed a string and will return that string every time it’s called, except the first time (in which case it returns an empty string). You can use this to join things

所以你的代码应该是这样的:

[
{% set comma = joiner(",") %}    
{% for host in play_hosts %}
    {{ comma() }}
    {{ "rabbitmq@%s"|format(host) }}
{% endfor %}
]

如果要格式化一个字符串,通过一个列表。

l: list = ["world", "Whosebug"]  
"Hello %s and %s"|format(*l)