【问题标题】:How to combine multiple dict variables into an array based on regex of dict variable names如何根据字典变量名的正则表达式将多个字典变量组合成一个数组
【发布时间】:2019-09-02 16:31:32
【问题描述】:

我的库存中有多个以“my_var_*”开头的 dict 变量。我想将这些组合成一个名为'my_var'的字典数组

在我的剧本中,我使用 'set_fact:' 来创建 'my_var' 变量,方法是尝试使用选择过滤器和匹配正则表达式从“hostvars ['localhost']”中提取匹配变量,但仅加入有效在弦上。

变量.yml

    my_var_1:
        element1: value11
        element2: value12
    my_var_2:
        element1: value21
        element2: value22

playbook.yml

    - hosts: localhost
      connection: local
      gather_facts: False
      tasks:
        - set_fact:
            my_var: "{{ hostvars['localhost'] | select('match', '^my_var_*') | join(', ' }}"
        - debug:
            msg: "{{ my_var }}"

是否可以像这样将这些 'dict' 变量加入到一个 'array' 中?

    my_var:
      - element1: value11
        element2: value12
      - element1: value21
        element2: value22

甚至可能

    my_var:
      - name: 1
        element1: value11
        element2: value12
      - name: 2
        element1: value21
        element2: value22

【问题讨论】:

    标签: merge ansible jinja2


    【解决方案1】:

    您非常接近,但正如您所指出的,字符串上的 join 方法用于连接字符串。您想要附加列表,您可以使用 + 运算符完成。

    还有一些其他问题:

    表达式:

    hostvars['localhost'] | select('match', '^my_var_*')
    

    将生成一个如下所示的列表:

    [
      "my_var_1",
      "my_var_2"
    ]
    

    ...这不是你想要的。您需要这些变量的,而不是键名。我们可以使用dict2items过滤器和selectattr过滤器来生成我们想要的数据:

    ---
    - hosts: localhost
      gather_facts: false
      tasks:
        - name: set facts on localhost
          set_fact:
            my_var_1:
                element1: value11
                element2: value12
            my_var_2:
                element1: value21
                element2: value22
    
    - hosts: localhost
      gather_facts: false
      tasks:
        - name: merge vars into my_var
          set_fact:
            my_var: "{{ hostvars['localhost']|dict2items|selectattr('key', 'match', '^my_var_')|map(attribute='value')|list }}"
    
        - name: show content of my_var
          debug:
            var: my_var
    

    这将产生以下输出:

    TASK [show content of my_var] ************************************************************************************
    ok: [localhost] => {
        "my_var": [
            {
                "element1": "value11", 
                "element2": "value12"
            }, 
            {
                "element1": "value21", 
                "element2": "value22"
            }
        ]
    }
    

    如果你去掉 map(attribute='value') 过滤器,你会得到:

    TASK [show content of my_var] *****************************************************************************************
    ok: [localhost] => {
        "my_var": [
            {
                "key": "my_var_1", 
                "value": {
                    "element1": "value11", 
                    "element2": "value12"
                }
            }, 
            {
                "key": "my_var_2", 
                "value": {
                    "element1": "value21", 
                    "element2": "value22"
                }
            }
        ]
    }
    

    这并不完全是您要求的第二个选项,但它确实包括键名和值。


    补充说明:

      1234563变量。你没有在你的问题中显示你是如何设置这些变量的,所以我不知道这是否会像写的那样工作。
    1. 在正则表达式中,* 表示“前面的字符零次或多次”,因此表达式 ^my_var_* 将匹配 my_varmy_var_1my_var______________my_varfoo 和等等。您可以简单地写^my_var_ 来选择您感兴趣的变量名称(这将选择以文本my_var_ 开头的任何内容)。

    【讨论】:

    • 是的,我知道我在使用正则表达式时做错了什么。我看到了 dict2items,但没有看到如何使用它。我现在看到了!这完美地工作。谢谢!!
    猜你喜欢
    • 1970-01-01
    • 2012-05-20
    • 2019-07-03
    • 2018-03-03
    • 1970-01-01
    • 1970-01-01
    • 2020-07-29
    • 2022-06-10
    • 2023-01-11
    相关资源
    最近更新 更多