如何附加到字符串列表中的每个项目?
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 没有库存
我有一个包含 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 没有库存