Jinja2 如何向字符串列表中的每个项追加?

Jinja2 如何向字符串列表中的每个项追加?,jinja2,salt-stack,Jinja2,Salt Stack,我有一个包含IP地址的字符串列表。我想给它们每个都附加一个端口号。在python中,我会这样做: ip_list = [(ip + ":" + port) for ip in ip_list] Match user *,!root,!fred,!jim,!bob,!arthur - set_fact: list_ip: "{% for ip in ip_list %}{{ip}}:{{port}}{% if not loop.last %},{% endif

我有一个包含IP地址的字符串列表。我想给它们每个都附加一个端口号。在python中,我会这样做:

ip_list = [(ip + ":" + port) for ip in ip_list]
Match user *,!root,!fred,!jim,!bob,!arthur
   - set_fact:
        list_ip: "{% for ip in ip_list %}{{ip}}:{{port}}{% if not loop.last %},{% endif %}{% endfor %}"
…但Jinja不支持列表理解。目前,我正在通过一次一项地创建一个新列表来解决这个问题:

{%- set ip_list = magic() %}
{%- set new_ip_list = [] %}
{%- for ip in ip_list %}
  {%- do new_ip_list.append(ip + ":" + port) %}
{%- endfor %}
这是一个模板中的丑陋和恼人的事情,感觉应该有一个更好的方法来完成这项工作。最好是一个班轮


虽然我知道这可以通过自定义过滤器实现,但我正在为我没有编写的软件(saltstack)提供一个模板,因此(据我所知)它们对我来说是不可用的。

没有任何语言的列表理解是令人讨厌的

你能使用“格式”过滤器吗


这一点也不漂亮,但对我来说很有效。我需要建立一个用户名列表,每个用户名前面都有一个“!”。此列表必须放置在用户之间带有逗号的行上

我的用户列表(设置为vars、defaults或其他)如下所示:

excluded_users: ["fred","jim","bob","arthur"]
在我的模板中,我有以下内容:

Match user *,!root{% if excluded_users|length > 0 %},!{{ excluded_users|join(",!") }}{% endif %}
…渲染和保存后,其外观如下所示:

ip_list = [(ip + ":" + port) for ip in ip_list]
Match user *,!root,!fred,!jim,!bob,!arthur
   - set_fact:
        list_ip: "{% for ip in ip_list %}{{ip}}:{{port}}{% if not loop.last %},{% endif %}{% endfor %}"

就像我说的,不是特别漂亮;-)

我对ansible的建议是:

magic() | map('regex_replace', '$', ':'~port) | list
映射:将筛选器应用于每个列表元素(如
liselement | replace(“$”,“:”~port)

替换:用
和端口替换字符串的结尾(因此附加它)
列表:将生成器转换为列表


使用regexp有点过分,但我的其他尝试甚至更多。不幸的是,
regex\u replace
确实如此。

只需迭代列表项,然后使用jinja2打印如下元素:

ip_list = [(ip + ":" + port) for ip in ip_list]
Match user *,!root,!fred,!jim,!bob,!arthur
   - set_fact:
        list_ip: "{% for ip in ip_list %}{{ip}}:{{port}}{% if not loop.last %},{% endif %}{% endfor %}"
lisp_ip变量将使用逗号分隔字符串ip:port。然后您可以拆分它以获得一个列表

lisp_ip.split(',')


我一直在使用
zip\u longest
在字符串列表中创建列表,然后将它们连接起来

ip_string_list|zip_longest([],fillvalue='some_port')| map('join')| list

当然,如果变量中有端口,则可以执行以下操作:

ip_字符串| zip_最长([],fillvalue=port_字符串)| map('join')|列表

您也可以在
join
操作中包含分隔符:

ip_string_list|zip_longest([],fillvalue=port_string)| map('join',':')| list

要在开始前抛出一个
反向

ip_string_list|zip_longest([],fillvalue=port_string)| map('reverse')| map('join',':')| list

我一直使用这种模式来构建LDAP可分辨名称


编辑:我在Ansible中就是这样做的,
zip\u longest
没有库存Jinja2

很遗憾,没有。我需要的结果是一个jinja字符串对象列表(稍后通过join()传递)。尽可能地负责任。