【问题标题】:Jinja2: format + join the items of a listJinja2:格式化+加入列表的项目
【发布时间】:2016-05-13 01:05:02
【问题描述】:

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 来指定通过管道传输的字符串?请帮助,蟒蛇僧侣!

【问题讨论】:

  • 这行得通吗? (我从没用过jinja){% for host in play_hosts %}{{ "rabbitmq@%s"|format(host) }}{% endfor %}
  • 似乎只需要一个列表理解。
  • @Barmar 列表组合不受 jinja2 支持

标签: python jinja2 ansible


【解决方案1】:

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

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

【讨论】:

  • 简化:{{ play_hosts | map('regex_replace', '^', 'rabbitmq@') | list }}
【解决方案2】:

您可以创建自定义过滤器

# /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') }}

【讨论】:

  • 我认为这是最好的解决方案。如果您尝试在剧本中完成所有操作,您的 Jinja2 代码将很快变得笨拙。
  • 这样的format_list真的应该是Jinja2的一部分!
【解决方案3】:

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

joiner 被传递一个字符串,每次调用时都会返回该字符串,但第一次调用除外(在这种情况下,它返回一个空字符串)。您可以使用它来加入事物

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

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

    • 重复不是很好,但看起来比regex_replace干净。真的缺少 jinja2 中的干净过滤器。 +1 解决方法
    • 如果列表为空,这将留下一个悬空的rabbitmq@
    【解决方案5】:

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

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

    【讨论】:

      猜你喜欢
      • 2021-03-29
      • 1970-01-01
      • 2013-01-20
      • 1970-01-01
      • 2011-04-02
      • 1970-01-01
      • 2015-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多