John Engineer
John Engineer

Reputation: 1

Ansible playbook for finding file string and then another string

I have a file that looks like this:

person:
   firstname=tom
   Prefix=mr
   lastname=jones

person:
   firstname=fred
   Prefix=mr
   lastname=dorfman

I want to find the string person and extract the value after the equal sign for firstname and lastname, for all occurrences of person.

I know how to find a string in a file, such as person but do know how to extract the following firstname and lastname values for all occurrences of person.

In the file, there could be only one occurrence of person or five.

Thank you very much from a newbie Ansible coder.

Upvotes: 0

Views: 60

Answers (1)

Alexander Pletnev
Alexander Pletnev

Reputation: 3516

This is a bit tricky, but possible. For the sake of simplicity, let's consider two restrictions:

  • the files are located in the same directory as the playbook
  • the order of the names is immutable - otherwise, the logic could be much more complex.

With that being said, we can:

  • find the files and loop over their content using lookup('file', item.path)
  • filter the lines that contain the first or the last name with | split() | select('match', '(lastname|firstname)=')
  • remove the "keys" so that only the names are retained using | map('regex_replace', '(lastname|firstname)=', ''). Note the usage of map here as otherwise the operation will be performed on the string, not on the list of strings
  • since we get a flat list, we can batch its items in groups of 2, representing the first name and the last name
  • and join these pairs to get the full names:
# playbook.yaml
---
- name: Find the names within the files
  hosts: localhost
  connection: local
  gather_facts: false
  tasks:
    - name: Find the matching files
      find:
        paths:
          - "{{ playbook_dir }}"
        patterns:
          - "*.txt"
        contains: person
        file_type: file
        depth: 1
        register: find_results

    - name: Find the names
      set_fact:
        names: >-
          {{
            names | default([]) +
            [
              lookup('file', item.path)
                | split()
                | select('match', '(lastname|firstname)=')
                | map('regex_replace', '(lastname|firstname)=', '')
                | batch(2)
                | map('join','')
            ]
          }}

      loop: "{{ find_results.files}}"
      loop_control:
        label: "{{ item.path }}"

    - name: List the names
      debug:
        var: names | flatten

Note the usage of loop_control.label that allows to clean up the playbook logs from the contents of the find module return values.

Upvotes: 2

Related Questions