# Parse complex data in ansible

**URL:** <https://forum.ansible.com/t/parse-complex-data-in-ansible/6964>\
**Category:** Get Help\
**Tags:** collections\
**Created:** [July 2, 2024, 9:23am UTC](https://forum.ansible.com/t/parse-complex-data-in-ansible/6964 "2024-07-02T09:23:17Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Neha001](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/neha001/32/4049_2.png) [@Neha001](https://forum.ansible.com/u/Neha001)\
**Post date:** [July 2, 2024, 9:23am UTC](https://forum.ansible.com/t/parse-complex-data-in-ansible/6964/1 "2024-07-02T09:23:17Z")

</div>

I have fetched data from remote firewall device using ssh in ansible .  
I got the context data in stdout\_lines in below format.I wanted to form a dict mapped with first and 3rd item in string.How to achieve so?Please help

- my code!

```auto
Example
Output of show context in ansible from remote cisco asa fw device
stdout_lines: [
                       [ 
                             "Context Name Class Interfaces Mode. URL"
                             " TD-BW-SNSL-Workplace default Port-channel1.2345, " Routed disk0:/
                             " Port-channel10.2298-"
                             " 2299, Port-,"
                             " channel20.2229 "                   
]
]

How can I get the context name and interface from this data in ansible?
```

---

<div class="post-metadata">

**Author:** ![mikemorency](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/mikemorency/32/2672_2.png) [@mikemorency](https://forum.ansible.com/u/mikemorency)\
**Post date:** [July 2, 2024, 1:02pm UTC](https://forum.ansible.com/t/parse-complex-data-in-ansible/6964/2 "2024-07-02T13:02:57Z")

</div>

The data youve provided is invalid yaml/json, and seems to be irregular as a table (theres no clear correlation between columns in each row). Can you try to provide a better example? As youve posted it, I dont think you can parse it really.

If we clean it up a bit:

```auto
# vars.yml
stdout_lines:
  [
    [
      "Context Name Class Interfaces Mode. URL",
      "TD-BW-SNSL-Workplace default Port-channel1.2345, Routed disk0:/",
      "c2 default Port-channel10.2298 Routed disk0:/",
    ],
  ]

```

Then this playbook parses it:

```auto
- hosts: localhost
  gather_facts: false
  vars_files:
    - vars.yml
  tasks:
    - set_fact:
        s: "{{ (stdout_lines)[0] }}"
    - set_fact:
        contexts: >-
          {{ (contexts | default([])) + [
            item.split()[0] | trim | trim(',')
          ] }}
        interfaces: >-
          {{ (interfaces | default([])) + [
            item.split()[2] | trim | trim(',')
          ] }}
      loop: "{{ s }}"
      when: not item.startswith('Context Name')

    - debug:
        var: contexts
    - debug:
        var: interfaces
    - debug:
        var: contexts | zip(interfaces) | community.general.dict

```

Heres the (partial) output

```auto
TASK [debug] ***********************************************************************************************************************************************************************************************************************************************
ok: [mikemorency] => {
    "contexts": [
        "TD-BW-SNSL-Workplace",
        "c2"
    ]
}

TASK [debug] ***********************************************************************************************************************************************************************************************************************************************
ok: [mikemorency] => {
    "interfaces": [
        "Port-channel1.2345",
        "Port-channel10.2298"
    ]
}

TASK [debug] ***********************************************************************************************************************************************************************************************************************************************
ok: [mikemorency] => {
    "contexts | zip(interfaces) | community.general.dict": {
        "TD-BW-SNSL-Workplace": "Port-channel1.2345",
        "c2": "Port-channel10.2298"
    }
}

```

---

<div class="post-metadata">

**Author:** ![mikemorency](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/mikemorency/32/2672_2.png) [@mikemorency](https://forum.ansible.com/u/mikemorency)\
**Post date:** [July 2, 2024, 2:07pm UTC](https://forum.ansible.com/t/parse-complex-data-in-ansible/6964/5 "2024-07-02T14:07:27Z")

</div>

> [@Neha001](#):
>
> Is there a way I can parse below data and include the remaining port channel from separate string to first row

Im not sure I understand, is this the value you want?

```auto
[
  "Port-channel1.2345",
  "Port-channel10.2298-2299",
  "Port-channel20.2229"
]

```

---

<div class="post-metadata">

**Author:** ![mikemorency](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/mikemorency/32/2672_2.png) [@mikemorency](https://forum.ansible.com/u/mikemorency)\
**Post date:** [July 2, 2024, 2:27pm UTC](https://forum.ansible.com/t/parse-complex-data-in-ansible/6964/8 "2024-07-02T14:27:27Z")

</div>

I see. This is a very challenging data format. It might be easier to look at ways to get better input data formats instead of parsing this.

Would you have a case where there are multiple contexts? Like

```auto
TD-BW-SNSL-Workplace
TD-BW-SNSL-Workplace1
TD-BW-SNSL-Workplace2

```

---

<div class="post-metadata">

**Author:** ![mikemorency](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/mikemorency/32/2672_2.png) [@mikemorency](https://forum.ansible.com/u/mikemorency)\
**Post date:** [July 2, 2024, 3:35pm UTC](https://forum.ansible.com/t/parse-complex-data-in-ansible/6964/10 "2024-07-02T15:35:00Z")

</div>

OK, really messy but here it is:

```auto
# vars.yml
context_names:
  [
    " ST-BW-SNSL-OPG-COMMSEE default Port-channel1.2345, Routed disk0:/ST-BW-SNSL-OPG-COMMSEE.cfg",
    " Port-channel10.2006-",
    " 2007,Port- ",
    " channel20.2224 ",
    " ST-BW-SNSL-COMMSEC-NONPROD default Port-channel1.2345, Routed disk0:/ST-BW-SNSL-COMMSEC-NONPROD.cfg",
    " Port-channel10.2273-",
    " 2276,Port- ",
    " channel20.2223 ",
    " ST-BW-SNSL-CYBERARK default Port-channel1.2345, Routed disk0:/ST-BW-SNSL-CYBERARK.cfg",
    " Port-channel10.2272,",
    " Port-channel20.2222 ",
    " ST-BW-SNSL-NON-STOP default Port-channel1.2345, Routed disk0:/ST-BW-SNSL-NON-STOP.cfg",
    " Port-channel10.2041-",
    " 2054,2108-2115,Port-",
    " channel20.2227 ",
    " ST-BW-SNSL-ENTERPRISE-MF default Port-channel1.2345, Routed disk0:/ST-BW-SNSL-ENTERPRISE-MF.cfg",
    " Port-channel10.2283,",
    " Port-channel20.2226 ",
    " ST-BW-SNSL-DOT default Port-channel1.2345, Routed disk0:/ST-BW-SNSL-DOT.cfg",
    " Port-channel10.2279-",
    " 2282,2284-2287,Port-",
    " channel20.2225 ",
    " ST-BW-SNSL-Internet-Browsing default Port-channel1.2345, Routed disk0:/ST-BW-SNSL-Internet-Browsing.cfg",
    " Port-channel10.1568,",
    " 1570,Port- ",
    " channel20.2228 ",
    " TD-BW-SNSL-Workplace default Port-channel1.2345, Routed disk0:/TD-BW-SNSL-Workplace.cfg",
    " Port-channel10.2298-",
    " 2299,Port- ",
    " channel20.2229 ",
    "",
    "Total active Security Contexts: 9",
  ]

```

```auto
# playbook.yml
- hosts: localhost
  gather_facts: false
  vars_files:
    - vars.yml
  tasks:
    - set_fact:
        context_indices: "{{ context_indices | default([]) + [idx] }}"
      when: item is search('^ \w') or not item
      loop: "{{ context_names }}"
      loop_control:
        index_var: idx

    - set_fact:
        context_groups: >-
          {{ context_groups | default([]) +
          [context_names[context_indices[idx]:context_indices[idx+1]]]
          }}
      when: context_indices[idx+1] is defined
      loop: "{{ context_indices }}"
      loop_control:
        index_var: idx

    - set_fact:
        contexts: "{{ contexts | default([]) + [(item | first | split())[0] | trim()] }}"
        port_channel_first: >-
          {{ port_channel_first | default([]) + [(item | first | split())[2] | trim()] }}
        port_channel_other: >-
          {{ port_channel_other | default([]) +
          [(item[1:] | map('trim') | join()) | default([])]
          }}
      loop: "{{ context_groups }}"

    - set_fact:
        port_channels: >-
          {{ port_channel_first | zip(port_channel_other) | map('join') | map('split', ',') }}

    - set_fact:
        context_port_channel_map: >-
          {{ contexts | zip(port_channels) | community.general.dict }}

    - debug:
        var: context_port_channel_map

```

Outputs:

```auto
TASK [debug] ***********************************************************************************************************************************************************************************************************************************************
ok: [mikemorency] => {
    "context_port_channel_map": {
        "ST-BW-SNSL-COMMSEC-NONPROD": [
            "Port-channel1.2345",
            "Port-channel10.2273-2276",
            "Port-channel20.2223"
        ],
        "ST-BW-SNSL-CYBERARK": [
            "Port-channel1.2345",
            "Port-channel10.2272",
            "Port-channel20.2222"
        ],
        "ST-BW-SNSL-DOT": [
            "Port-channel1.2345",
            "Port-channel10.2279-2282",
            "2284-2287",
            "Port-channel20.2225"
        ],
        "ST-BW-SNSL-ENTERPRISE-MF": [
            "Port-channel1.2345",
            "Port-channel10.2283",
            "Port-channel20.2226"
        ],
        "ST-BW-SNSL-Internet-Browsing": [
            "Port-channel1.2345",
            "Port-channel10.1568",
            "1570",
            "Port-channel20.2228"
        ],
        "ST-BW-SNSL-NON-STOP": [
            "Port-channel1.2345",
            "Port-channel10.2041-2054",
            "2108-2115",
            "Port-channel20.2227"
        ],
        "ST-BW-SNSL-OPG-COMMSEE": [
            "Port-channel1.2345",
            "Port-channel10.2006-2007",
            "Port-channel20.2224"
        ],
        "TD-BW-SNSL-Workplace": [
            "Port-channel1.2345",
            "Port-channel10.2298-2299",
            "Port-channel20.2229"
        ]
    }
}

```

---

<div class="post-metadata">

**Author:** ![mikemorency](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/mikemorency/32/2672_2.png) [@mikemorency](https://forum.ansible.com/u/mikemorency)\
**Post date:** [July 2, 2024, 6:43pm UTC](https://forum.ansible.com/t/parse-complex-data-in-ansible/6964/13 "2024-07-02T18:43:54Z")

</div>

You can search on Ansible galaxy, check here  
[https://docs.ansible.com/ansible/latest/collections/index.html](https://docs.ansible.com/ansible/latest/collections/index.html)  
or check here  
[https://docs.ansible.com/ansible/latest/collections/community/general/index.html#plugins-in-community-general](https://docs.ansible.com/ansible/latest/collections/community/general/index.html#plugins-in-community-general)
