如何附加到字符串列表中的每个项目?

How do I append to each item in a list of strings?

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

ip_list = [(ip + ":" + port) for ip in ip_list]

...但是 Jinja 不支持列表理解。目前,我正在通过一次构建一个新列表来解决这个问题:

{%- set ip_list = magic() %}
{%- set new_ip_list = [] %}
{%- for ip in ip_list %}
  {%- do new_ip_list.append(ip + ":" + port) %}
{%- endfor %}

这在模板中间很丑陋且令人恼火,感觉确实应该有更好的方法来完成工作。最好是单线。

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

在任何语言中都没有列表理解很烦人!

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

{% for ip in magic() -%}
curl_host_port:
  cmd.run:
    - name: {{ "curl 'http://%s:80/'"|format(ip) }}
{% endfor -%}

这绝不是漂亮的,但这对我有用。我需要建立一个带有“!”的用户名列表在每个人面前。此列表必须放在一行中,用户之间用逗号隔开。

我的用户列表(在变量、默认值或其他设置中设置)如下所示:

excluded_users: ["fred","jim","bob","arthur"]

在我的模板中我有这个:

Match user *,!root{% if excluded_users|length > 0 %},!{{ excluded_users|join(",!") }}{% endif %}

...渲染并保存后,它看起来像这样:

Match user *,!root,!fred,!jim,!bob,!arthur

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

regex_replace 可以做到这一点。它在 ansible and saltstack:

可用
magic() | map('regex_replace', '$', ':'~port) | list
  • map:将 regex_replace 过滤器应用于每个列表元素(如 listElement | regex_replace('$', ':'~port)
  • replace:用 : 和端口替换字符串的结尾(所以附加它)
  • 列表:将生成器转换为列表

使用正则表达式有点矫枉过正,但我​​的其他尝试更是如此。很遗憾 regex_replace does not exist in normal jinja.

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

   - 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_longest 在字符串列表中创建列表,然后加入它们。

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

当然,如果你在变量中有端口,你可以这样做:

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

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

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

要在 reverse:

前抛出

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

我一直使用这种模式来构建 LDAP 专有名称。

编辑:这就是我在 Ansible 中的做法,zip_longest Jinja2 没有库存