如何从一个值和一个值列表构建一个字符串?

时间:2019-05-23 00:24:52

标签: ansible ansible-template

[第一次提问者。我认为,我已将其定位为一个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 }}"

但是由于无法将字符串内插到fillvalue中,所以我陷入了困境。

我在format过滤器周围胡闹,但它似乎将输出字符串作为输入,并将值作为参数,这与我的情况相反。

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

如果您不介意一对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:\1".format(gid))) }}'

- debug:
    var: rules_str_2

要使此set_fact任务按编写的方式工作,您必须在外部使用单引号(这禁止使用\作为转义符)。您可以交换引号,但随后需要写\\而不是\。回忆匹配表达式中的(...)创建了一个捕获组,替换字符串中的\1扩展为第一个捕获组的值。


将所有内容放到一本剧本中

---
- 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:\1".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