how to select regex matches in jinja2?
I found the following trick if you want to filter a list in Ansible (get the list with null values and make difference with null list) :
---
- hosts: localhost
connection: local
vars:
regexp: '.*a[rp].*'
empty: [null]
tasks:
- set_fact: matches="{{ ['hello', 'apple', 'rare', 'trim', 'three'] | map('regex_search',regexp) | list|difference(empty) }}"
- debug: msg="{{ matches }}"
Here is the output :
ok: [localhost] => {
"msg": [
"apple",
"rare"
]
}
Will this do?
---
- hosts: localhost
connection: local
vars:
my_list: ['hello', 'apple', 'rare', 'trim', 'three']
my_pattern: '.*a[rp].*'
tasks:
- set_fact: matches="{{ my_list | map('regex_search',my_pattern) | select('string') | list }}"
failed_when: matches | count > 1
- debug: msg="I'm the only one - {{ matches[0] }}"
Update: how it works...
map applies filters – filters are not yes/no things, they applied to every item of input list and return list of modified items. I use
regex_search
filter, which search pattern in every item and return a match if found or None if there is no match. So on this step I get this list:[null, "apple", "rare", null, null]
.Then we use select, which applies tests – tests are yes/no things, so they reduce the list based on selected test. I use
string
test, which is true when item of a list is string. So we get:["apple", "rare"]
.map
andselect
give us some internal python types, so we convert to list by applyinglist
filter after all.
This design pattern worked for me:
----
- hosts: localhost
connection: local
vars:
my_list: ['hello', 'apple', 'rare', 'trim', "apropos", 'three']
my_pattern: 'a[rp].*'
tasks:
- set_fact:
matches: "{%- set tmp = [] -%}
{%- for elem in my_list | map('match', my_pattern) | list -%}
{%- if elem -%}
{{ tmp.append(my_list[loop.index - 1]) }}
{%- endif -%}
{%- endfor -%}
{{ tmp }}"
- debug:
var: matches
failed_when: "(matches | length) > 1"