在Ansible / Jinja中,是否有一种方法可以使用k:v对字典来用整数替换字符串?

时间:2020-03-13 13:42:14

标签: regex dictionary ansible jinja2

注意:原始问题在此处展开​​:Is there a way in Ansible to replace a dictionary value based on k:v lookup to another dictionary?

我有3个字典,前2个是k:v,具有string:integer类型值;我的第三个字典是string:string的ak:v,我想先用dict#1循环遍历,然后用k:v替换k,然后与dict#2相同,但用k:v替换v。

"dict_1": {
    "office-core01": 85,
    "office-core02": 86,
    "office-fw01": 87,
    "office-fw02": 88,
    "office-server-sw01": 91,
    "office-vpn01": 92,
    "office-vpn02": 93
}
"dict_2": {
    "con1": 129,
    "con2": 130,
    "con3": 131,
    "con4": 132,
    "con5": 133,
    "con6": 134,
    "con7": 135,
    "con8": 136,
    "con9": 137
}
"dict_3": {
    "office-core01": "con1", 
    "office-core02": "con2", 
    "office-fw01": "con3", 
    "office-fw02": "con4", 
    "office-server-sw01": "con7", 
    "office-vpn01": "con5", 
    "office-vpn02": "con6"
}

最后,我需要k:v对整数的字典;例如,在第一次迭代中,我需要用替换为dict_1( 85 )中的值的dict_3中的主机名/密钥( office-core01 ),然后进行第二次替换端口/ values( con1 )替换为dict_2( 129 )中的键,但是使用弗拉基米尔(Vladimir)提供的代码在原始问题中抱怨object of type 'int' has no len()

包含任务( console-portid.yml ):

---
  - name: Replace Console Hostname ID
    set_fact:
      port_mapping: "{{ port_mapping | difference([item]) +
                        [dict(my_value | zip(my_keys))] }}"
    vars:
      my_key: "{{ item.keys() | list }}"
      my_value: "{{ item.values() | list }}"
      my_keys: "{{ my_key | map('regex_replace', port_id.key, port_id.value) | list }}"
    loop: "{{ dict_3 | dict2items }}"

调用:

- name: Replace Device Console Ports ID
  include_tasks: console-portid.yml
  loop: "{{ dict_1 | dict2items }}"
  loop_control:
    loop_var: port_id

2 个答案:

答案 0 :(得分:1)

Q:“我想将office-core01:con1变成85:129”

A:下面的任务可以完成

    - set_fact:
        dict_3a: "{{ dict_3a|default({})|
                     combine({dict_1[item.key]: dict_2[item.value]}) }}"
      loop: "{{ dict_3|dict2items }}"
    - debug:
        var: dict_3a

给予

    "dict_3a": {
        "85": 129, 
        "86": 130, 
        "87": 131, 
        "88": 132, 
        "91": 135, 
        "92": 133, 
        "93": 134
    }

Q:“是否有一个原因键是字符串,并且值仍然是整数?”

A:保留变量的内部类型。除非由DEFAULT_JINJA2_NATIVE进行配置,否则变量的结果为字符串。引用“此选项在模板操作期间保留变量类型。这需要Jinja2> = 2.10。”


Q:“键是否为字符串且值仍为整数?键总是必须为字符串吗?”

A:按键没有限制。引用3.2.1.1. Nodes

” YAML节点表示单个本地数据结构。此类节点具有以下三种内容之一:标量,序列或映射。此外,每个节点都有一个标记,用于限制可能的集合内容可以具有的值。“

“映射:映射节点的内容是一组无序的键:值节点对,每个键都是唯一的限制。YAML对该节点没有进一步的限制。可以是任意n 颂歌,同一节点可以用作多个键的值:值对,并且映射甚至可以包含自身作为键或值(直接或间接)。”

答案 1 :(得分:1)

---
- hosts: localhost
  gather_facts: no
  tasks:
  - name: Loop over dict_3
    debug:
      msg: "{{ item.key }}: {{ item.value }}"
    with_items: "{{ lookup('dict', dict_3) }}"

  - name: Loop over dict_3 with replacements
    debug:
      msg: "{{ dict_1[item.key] }}: {{ dict_2[item.value] }}"
    with_items: "{{ lookup('dict', dict_3) }}"

  - name: Create new dictionary
    set_fact:
      dict_4: "{{ dict_4|default({}) | combine( {dict_1[item.key]: dict_2[item.value]} ) }}"
    with_items: "{{ lookup('dict', dict_3) }}"

  - name: Show dict_4
    debug:
      var: dict_4
相关问题