regexansibleyamljinja2

Apply multiple regexp from dict on a field and get result for each


I am trying to apply multiple regexp to a string field and return true if it matchs for each. Here is my dictionary containing all the regexp :

myconfig:
  kindA:
    regexp: "^exampleA.+$"
  kindB:
    regexp: "^exampleB.+$"
  kindC:
    regexp: "^exampleC.+$"

Desired result:

{
  "kindA": false,
  "kindB": true, # description field matched !
  "kindC": false
}

The code I try in my playbook :

- ansible.builtin.set_fact:
   regex_result: "{{ regex_result | default({}) |
     combine({ item.key: (my_current_obj.description
       | regex_search(item.value.regexp)
       | bool) }
     }}"
 loop: "{{ lookup('dict', myconfig) }}"

I feel like it should work but linter says this template is invalid.


Solution

  •   regex: "{{ myconfig | dict2items | map(attribute='value.regexp') }}"
    

    gives

      regex:
        - ^exampleA.+$
        - ^exampleB.+$
        - ^exampleC.+$
    

    If you want to use default with variables that evaluate to false you have to set the second parameter to true.

    This helps you to convert None to an empty string and test the length

      search: |
        [
        {% for r in regex %}
        {{ description | regex_search(r) | d('', true) | length > 0 }},
        {% endfor %}
        ]
    

    gives for example, for description=exampleAX

      search:
        - true
        - false
        - false
    
      result: "{{ dict(myconfig | zip(search)) }}"
    

    gives what you want

      result:
        kindA: true
        kindB: false
        kindC: false
    

    As a side note: A simple option is searching joined regex

      result: "{{ description | regex_search(regex | join('|'))
                              | d('', true)
                              | length > 0 }}"
    

    Example of a complete playbook for testing

    - hosts: localhost
    
      vars:
    
        myconfig:
          kindA:
            regexp: "^exampleA.+$"
          kindB:
            regexp: "^exampleB.+$"
          kindC:
            regexp: "^exampleC.+$"
    
        regex: "{{ myconfig | dict2items | map(attribute='value.regexp') }}"
        search: |
          [
          {% for r in regex %}
          {{ description | regex_search(r) | d('', true) | length > 0 }},
          {% endfor %}
          ]
    
        result: "{{ dict(myconfig | zip(search)) }}"
        resul2: "{{ description | regex_search(regex | join('|'))
                                | d('', true)
                                | length > 0 }}"
    
      tasks:
    
        - debug:
            var: regex
        - debug:
            var: search
        - debug:
            var: result
        - debug:
            var: resul2
    
    shell> ansible-playbook pb.yml -e description=exampleAX
    
    PLAY [localhost] ****************************************************************************************************
    
    TASK [debug] ********************************************************************************************************
    ok: [localhost] => 
        regex:
        - ^exampleA.+$
        - ^exampleB.+$
        - ^exampleC.+$
    
    TASK [debug] ********************************************************************************************************
    ok: [localhost] => 
        search:
        - true
        - false
        - false
    
    TASK [debug] ********************************************************************************************************
    ok: [localhost] => 
        result:
            kindA: true
            kindB: false
            kindC: false
    
    TASK [debug] ********************************************************************************************************
    ok: [localhost] => 
        resul2: true
    
    PLAY RECAP **********************************************************************************************************
    localhost                  : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0