# Filtering a nested structure in Jinja2, regexp matches?

**URL:** <https://forum.ansible.com/t/filtering-a-nested-structure-in-jinja2-regexp-matches/27403>\
**Category:** Ansible Project\
**Created:** [April 29, 2018, 8:32am UTC](https://forum.ansible.com/t/filtering-a-nested-structure-in-jinja2-regexp-matches/27403 "2018-04-29T08:32:56Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Andy\_Smith](https://avatars.discourse-cdn.com/v4/letter/a/898d66/32.png) [@Andy\_Smith](https://forum.ansible.com/u/Andy_Smith)\
**Post date:** [April 29, 2018, 8:32am UTC](https://forum.ansible.com/t/filtering-a-nested-structure-in-jinja2-regexp-matches/27403/1 "2018-04-29T08:32:56Z")

</div>

Hi,

I'd like to produce a template which lists disk device links. These  
are the things you might find in /dev/disk/by-id/\*, e.g.:

$ ls /dev/disk/by-id  
ata-SomeVendor\_AAAAAAAAAAAA-00005\_BBBBBBBBBBBBBB  
ata-ST4000LM016-1N2170\_W801ZG92  
ata-OtherVendor\_SSD\_OVCCCCCCCCCCCCCCCCCC  
ata-OtherVendor\_SSD\_OVCCCCCCCCCCCCCCCCCC-part1  
ata-OtherVendor\_SSD\_OVCDDDDDDDDDDDDDDDDD  
ata-OtherVendor\_SSD\_OVCDDDDDDDDDDDDDDDDD-part1  
dm-name-somevg-somelv  
dm-uuid-LVM-0ysSbtTVMkvV21YB9629d3ey3fljIuPZDJSrQdwdIrPdXShmIRJxAexoxC3Of2OB  
.  
.  
.  
etc

These are available inside the "ansible\_device\_links" fact like this:

talisker | SUCCESS =\> {  
&nbsp;&nbsp;&nbsp;&nbsp;"ansible\_facts": {  
.  
.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"ansible\_device\_links": {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"ids": {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"dm-10": [  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"dm-name-somevg-somelv",  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"dm-uuid-LVM-A5XH2ZUDE0z4zFHu4s2IRtrcXgIsa6VDsZcUg5DaoduHYNfFKTvTqX2VKQ8zryj0"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;],  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"sdb": [  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"ata-SomeVendor\_AAAAAAAAAAAA-00005\_BBBBBBBBBBBBBB",  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"wwn-0x5002538c405ccf9f"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;],  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"sde": [  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"ata-OtherVendor\_SSD\_OVCCCCCCCCCCCCCCCCCC",  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"wwn-0x515d90417a000100"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;],  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"sde1": [  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"ata-OtherVendor\_SSD\_OVCCCCCCCCCCCCCCCCCC-part1",  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"wwn-0x515d90417a000100-part1"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;],  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"sdf": [  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"ata-OtherVendor\_SSD\_OVCDDDDDDDDDDDDDDDDD",  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"wwn-0x515d90417a000067"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;],  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"sdf1": [  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"ata-OtherVendor\_SSD\_OVCDDDDDDDDDDDDDDDDD-part1",  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"wwn-0x515d90417a000067-part1"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;],  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},  
.  
.  
}

I'm only interested in devices that begin with "ata-" and I don't  
want to consider partitions, so anything that ends with "-partX" is  
also not of interest.

I came up with the following Jinja2 template which works:

{% for dev, ids in ansible\_device\_links.ids.iteritems() %}  
{% if "ata-" in ids[0] and "-part" not in ids[0] %}{{ ids[0] }}{% endif %}  
{% endfor %}

That gets me a simple list like:

ata-SomeVendor\_AAAAAAAAAAAA-00005\_BBBBBBBBBBBBBB  
ata-OtherVendor\_SSD\_OVCCCCCCCCCCCCCCCCCC  
ata-OtherVendor\_SSD\_OVCDDDDDDDDDDDDDDDDD

Which is what I want.

My questions are:

- Could this be done more elegantly with some sort of map and/or  
&nbsp;&nbsp;selectattr filter?

- Is there any way to do a regexp match? I am concerned that without  
&nbsp;&nbsp;anchoring the "ata-" at the start or including the digits of the  
&nbsp;&nbsp;"-partX" bits that these strings could one day occur elsewhere in  
&nbsp;&nbsp;the id and erroneously exclude devices.

Thanks,  
Andy

---

<div class="post-metadata">

**Author:** ![Kai\_Stian\_Olstad](https://avatars.discourse-cdn.com/v4/letter/k/e19adc/32.png) [@Kai\_Stian\_Olstad](https://forum.ansible.com/u/Kai_Stian_Olstad)\
**Post date:** [April 29, 2018, 9:48am UTC](https://forum.ansible.com/t/filtering-a-nested-structure-in-jinja2-regexp-matches/27403/2 "2018-04-29T09:48:09Z")

</div>

For the regex you could do this

{% for dev, ids in ansible\_device\_links.ids.iteritems() if ids.0.startswith('ata-') and not ids.0 | regex\_search('-part[0-9]+$') %}  
{{ ids[0] }}  
{% endfor %}

---

<div class="post-metadata">

**Author:** ![Andy\_Smith](https://avatars.discourse-cdn.com/v4/letter/a/898d66/32.png) [@Andy\_Smith](https://forum.ansible.com/u/Andy_Smith)\
**Post date:** [April 29, 2018, 10:37am UTC](https://forum.ansible.com/t/filtering-a-nested-structure-in-jinja2-regexp-matches/27403/3 "2018-04-29T10:37:30Z")

</div>

Hi Kai,

> \>- Is there any way to do a regexp match? I am concerned that without  
> \> anchoring the "ata-" at the start or including the digits of the  
> \> "-partX" bits that these strings could one day occur elsewhere in  
> \> the id and erroneously exclude devices.
> 
> For the regex you could do this
> 
> {% for dev, ids in ansible\_device\_links.ids.iteritems() if  
> ids.0.startswith('ata-') and not ids.0 | regex\_search('-part[0-9]+$') %}  
> {{ ids[0] }}  
> {% endfor %}

Thank you very much!

I'm new to Jinja2 and was basing what I could do with it on the  
contents of [http://jinja.pocoo.org/docs/2.10/templates/](http://jinja.pocoo.org/docs/2.10/templates/). This has no  
matches for "regex" so I thought I couldn't do that, and I also  
didn't realise that I could use a method of a string object like  
"startswith".

I see now that I should have been looking in the Ansible  
documentation for filters, i.e.:  
[http://docs.ansible.com/ansible/latest/user\_guide/playbooks\_filters.html#regular-expression-filters](http://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#regular-expression-filters)

Cheers,  
Andy
