如何从一个值和一个值列表构建一个字符串?
How can I build a string from a value and a list of values?
[第一次提问。我 认为 我已将其定位为 Ansible 问题。如果没有,欢迎温和的重定向!]
鉴于:
gid: 80
ports: [80, 443]
其中端口的数量可能从 0 到很多不等
我想生成这样的字符串:
"gid:80:tcp:80,gid:80:tcp:443"
(恰好是 FreeBSD mac_portacl 规则字符串)
我得到的最远的是:
portacl_rules: "{{ ports | zip_longest([], fillvalue='80') | list }}"
这给了我这样的东西:
"msg": [
[
80,
"80"
],
[
443,
"80"
]
]
但是:
- gid 是硬编码的,我不知道如何插入变量值;和
- 我无法将列表转换为最终字符串。
我可以创建 gid 字符串,gid:80
通过定义一个临时变量:
gid: 80
_tmp_gid: "gid:{{ gid }}"
但是由于我无法将字符串插入到填充值中,所以我被卡住了。
我在 format
过滤器周围胡闹,但它似乎将输出字符串作为其输入并将值作为其参数,这与我的情况相反。
有什么建议吗?
如果你不介意一对 set_fact
任务,你可以这样做:
- set_fact:
rules_list: "{{ rules_list|default([]) + ['gid:{}:tcp:{}'.format(gid, item)] }}"
loop: "{{ ports }}"
- set_fact:
rules_str_1: "{{ ','.join(rules_list) }}"
- debug:
var: rules_str_1
第一个任务创建以下形式的列表:
[
"gid:80:tcp:80",
"gid:80:tcp:443"
]
第二个任务使用 ,
连接这些项目。
您可以使用涉及 regex_replace
过滤器的稍微复杂的表达式在单个操作中完成该操作:
- set_fact:
rules_str_2: '{{ ",".join(ports|map("regex_replace", "^(.*)$", "gid:{}:tcp:".format(gid))) }}'
- debug:
var: rules_str_2
要使 set_fact
任务按书面方式工作,您 必须 在外部使用单引号(这禁止使用 \
作为转义符特点)。你可以交换引号,但是你需要写 \
而不是 \
。回想一下,匹配表达式中的 (...)
创建了一个捕获组,替换字符串中的 </code> 扩展为第一个捕获组的值。</p>
<hr>
<p>将所有内容放在剧本中:</p>
<pre><code>---
- hosts: localhost
gather_facts: false
vars:
gid: 80
ports: [80, 443]
tasks:
- set_fact:
rules_list: "{{ rules_list|default([]) + ['gid:{}:tcp:{}'.format(gid, item)] }}"
loop: "{{ ports }}"
- set_fact:
rules_str_1: "{{ ','.join(rules_list) }}"
- debug:
var: rules_str_1
- set_fact:
rules_str_2: '{{ ",".join(ports|map("regex_replace", "(.*)", "gid:{}:tcp:".format(gid))) }}'
- debug:
var: rules_str_2
这将产生以下输出:
PLAY [localhost] ******************************************************************************************************************************************************************************
TASK [set_fact] *******************************************************************************************************************************************************************************
ok: [localhost] => (item=80)
ok: [localhost] => (item=443)
TASK [set_fact] *******************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
"rules_str_1": "gid:80:tcp:80,gid:80:tcp:443"
}
TASK [set_fact] *******************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
"rules_str_2": "gid:80:tcp:80,gid:80:tcp:443"
}
PLAY RECAP ************************************************************************************************************************************************************************************
localhost : ok=5 changed=0 unreachable=0 failed=0
[第一次提问。我 认为 我已将其定位为 Ansible 问题。如果没有,欢迎温和的重定向!]
鉴于:
gid: 80
ports: [80, 443]
其中端口的数量可能从 0 到很多不等
我想生成这样的字符串:
"gid:80:tcp:80,gid:80:tcp:443"
(恰好是 FreeBSD mac_portacl 规则字符串)
我得到的最远的是:
portacl_rules: "{{ ports | zip_longest([], fillvalue='80') | list }}"
这给了我这样的东西:
"msg": [
[
80,
"80"
],
[
443,
"80"
]
]
但是:
- gid 是硬编码的,我不知道如何插入变量值;和
- 我无法将列表转换为最终字符串。
我可以创建 gid 字符串,gid:80
通过定义一个临时变量:
gid: 80
_tmp_gid: "gid:{{ gid }}"
但是由于我无法将字符串插入到填充值中,所以我被卡住了。
我在 format
过滤器周围胡闹,但它似乎将输出字符串作为其输入并将值作为其参数,这与我的情况相反。
有什么建议吗?
如果你不介意一对 set_fact
任务,你可以这样做:
- set_fact:
rules_list: "{{ rules_list|default([]) + ['gid:{}:tcp:{}'.format(gid, item)] }}"
loop: "{{ ports }}"
- set_fact:
rules_str_1: "{{ ','.join(rules_list) }}"
- debug:
var: rules_str_1
第一个任务创建以下形式的列表:
[
"gid:80:tcp:80",
"gid:80:tcp:443"
]
第二个任务使用 ,
连接这些项目。
您可以使用涉及 regex_replace
过滤器的稍微复杂的表达式在单个操作中完成该操作:
- set_fact:
rules_str_2: '{{ ",".join(ports|map("regex_replace", "^(.*)$", "gid:{}:tcp:".format(gid))) }}'
- debug:
var: rules_str_2
要使 set_fact
任务按书面方式工作,您 必须 在外部使用单引号(这禁止使用 \
作为转义符特点)。你可以交换引号,但是你需要写 \
而不是 \
。回想一下,匹配表达式中的 (...)
创建了一个捕获组,替换字符串中的 </code> 扩展为第一个捕获组的值。</p>
<hr>
<p>将所有内容放在剧本中:</p>
<pre><code>---
- hosts: localhost
gather_facts: false
vars:
gid: 80
ports: [80, 443]
tasks:
- set_fact:
rules_list: "{{ rules_list|default([]) + ['gid:{}:tcp:{}'.format(gid, item)] }}"
loop: "{{ ports }}"
- set_fact:
rules_str_1: "{{ ','.join(rules_list) }}"
- debug:
var: rules_str_1
- set_fact:
rules_str_2: '{{ ",".join(ports|map("regex_replace", "(.*)", "gid:{}:tcp:".format(gid))) }}'
- debug:
var: rules_str_2
这将产生以下输出:
PLAY [localhost] ******************************************************************************************************************************************************************************
TASK [set_fact] *******************************************************************************************************************************************************************************
ok: [localhost] => (item=80)
ok: [localhost] => (item=443)
TASK [set_fact] *******************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
"rules_str_1": "gid:80:tcp:80,gid:80:tcp:443"
}
TASK [set_fact] *******************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
"rules_str_2": "gid:80:tcp:80,gid:80:tcp:443"
}
PLAY RECAP ************************************************************************************************************************************************************************************
localhost : ok=5 changed=0 unreachable=0 failed=0