Noob
Noob

Reputation: 23

compare 2 files and get 3rd file

I have 2 csv files as

CSV1:
 ABC, NIC.Slot.1-1-1:, A6:C3:4F:8E:D5:30
 DEF, NIC.Slot.1-2-1:, B2:D5:8C:5A:43:60

CSV2:
 XYZ, ethernet15:3, ABC_DPDK2, b2:d5:8c:5a:43:60 
 UVW, ethernet15:2, ABC_DPDK1, a6:c3:4f:8e:d5:30

I want another CSV file which will compare the MAC of both the files and update rest in output csv file

Below is the desired output

CSV3:
    ABC, UVW, NIC.Slot.1-1-1:, A6:C3:4F:8E:D5:30, ethernet15:2, ABC_DPDK1
    DEF, XYZ, NIC.Slot.1-2-1:, B2:D5:8C:5A:43:60, ethernet15:3, ABC_DPDK2

is there anyway i can do it via ansible

Upvotes: 1

Views: 213

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 68034

Given the files

shell> cat net1.csv
ABC, NIC.Slot.1-1-1:, A6:C3:4F:8E:D5:30
DEF, NIC.Slot.1-2-1:, B2:D5:8C:5A:43:60
shell> cat net2.csv
XYZ, ethernet15:3, ABC_DPDK2, b2:d5:8c:5a:43:60 
UVW, ethernet15:2, ABC_DPDK1, a6:c3:4f:8e:d5:30

Put the declarations below as appropriate

    fields: [name1, name2, nic, MAC, dev, label]
    csv_files:
      - {file: net1.csv, fields: [name1, nic, mac]}
      - {file: net2.csv, fields: [name2, dev, label, mac]}
    _list: "{{ csv.results|map(attribute='list')|flatten }}"
    _MAC: "{{ _list|map(attribute='mac')|map('trim')|map('upper')|
                    map('community.general.dict_kv', 'MAC')|list }}"
    _groups: "{{ _list|zip(_MAC)|map('combine')|groupby('MAC') }}"
    _values: "{{ _groups|map(attribute=1)|map('combine')|list }}"

Read the files, for example

    - community.general.read_csv:
        path: "{{ playbook_dir }}/{{ item.file }}"
        fieldnames: "{{ item.fields }}"
        skipinitialspace: true
      register: csv
      loop: "{{ csv_files }}"

gives

_list:
  - mac: A6:C3:4F:8E:D5:30
    name1: ABC
    nic: 'NIC.Slot.1-1-1:'
  - mac: B2:D5:8C:5A:43:60
    name1: DEF
    nic: 'NIC.Slot.1-2-1:'
  - dev: ethernet15:3
    label: ABC_DPDK2
    mac: 'b2:d5:8c:5a:43:60 '
    name2: XYZ
  - dev: ethernet15:2
    label: ABC_DPDK1
    mac: a6:c3:4f:8e:d5:30
    name2: UVW
_values:
  - MAC: A6:C3:4F:8E:D5:30
    dev: ethernet15:2
    label: ABC_DPDK1
    mac: a6:c3:4f:8e:d5:30
    name1: ABC
    name2: UVW
    nic: 'NIC.Slot.1-1-1:'
  - MAC: B2:D5:8C:5A:43:60
    dev: ethernet15:3
    label: ABC_DPDK2
    mac: 'b2:d5:8c:5a:43:60 '
    name1: DEF
    name2: XYZ
    nic: 'NIC.Slot.1-2-1:'

Create the CSV file

    - ansible.builtin.copy:
        dest: net3.csv
        content: |-
          {% for line in _values %}
          {{ fields|map('extract', line)|join(', ') }}
          {% endfor %}

gives

shell> cat ~/net3.csv 
ABC, UVW, NIC.Slot.1-1-1:, A6:C3:4F:8E:D5:30, ethernet15:2, ABC_DPDK1
DEF, XYZ, NIC.Slot.1-2-1:, B2:D5:8C:5A:43:60, ethernet15:3, ABC_DPDK2

Example of a complete playbook

- hosts: localhost

  vars:
    fields: [name1, name2, nic, MAC, dev, label]
    csv_files:
      - {file: net1.csv, fields: [name1, nic, mac]}
      - {file: net2.csv, fields: [name2, dev, label, mac]}
    _list: "{{ csv.results|map(attribute='list')|flatten }}"
    _MAC: "{{ _list|map(attribute='mac')|map('trim')|map('upper')|
                    map('community.general.dict_kv', 'MAC')|list }}"
    _groups: "{{ _list|zip(_MAC)|map('combine')|groupby('MAC') }}"
    _values: "{{ _groups|map(attribute=1)|map('combine')|list }}"

  tasks:
    - community.general.read_csv:
        path: "{{ playbook_dir }}/{{ item.file }}"
        fieldnames: "{{ item.fields }}"
        skipinitialspace: true
      register: csv
      loop: "{{ csv_files }}"
    - ansible.builtin.copy:
        dest: net3.csv
        content: |-
          {% for line in _values %}
          {{ fields|map('extract', line)|join(', ') }}
          {% endfor %}

Upvotes: 2

Related Questions