Reputation: 603
Is there a way to sort a list in Ansible or Jinja in a natural way?
For example this is the list
test
test123
test12
test5
test1234test
test22te
And I need it to take in account the numbers as whole not as individual so test12
is under test5
and so on.
Upvotes: 2
Views: 1915
Reputation: 68044
Given the list
l1:
- test
- test123
- test12
- test5
- test1234test
- test22te
Create a list with an attribute index of type integer, e.g.
- set_fact:
l2: "{{ l2|default([]) +
[{'index': (_index|length > 0)|ternary(_index|int, 0),
'name': item}] }}"
loop: "{{ l1 }}"
vars:
_regex: '^test(\d*)\D*$'
_replace: '\1'
_index: "{{ item|regex_replace(_regex, _replace) }}"
- debug:
msg: "{{ l2|sort(attribute='index')|
map(attribute='name')|
list }}"
gives
msg:
- test
- test5
- test12
- test22te
- test123
- test1234test
Without iteration, declare the variables
_regex: '^test(\d*)\D*$'
_replace: '\1'
_index: "{{ l1|map('regex_replace', _regex, _replace)|map('int')|list }}"
l2: "{{ dict(_index|zip(l1))|
dict2items|
sort(attribute='key')|
map(attribute='value')|
list }}"
gives the same result
l2:
- test
- test5
- test12
- test22te
- test123
- test1234test
Example of a complete playbook for testing
- hosts: localhost
vars:
l1:
- test
- test123
- test12
- test5
- test1234test
- test22te
_regex: '^test(\d*)\D*$'
_replace: '\1'
_index: "{{ l1|map('regex_replace', _regex, _replace)|map('int')|list }}"
l2: "{{ dict(_index|zip(l1))|
dict2items|
sort(attribute='key')|
map(attribute='value')|
list }}"
tasks:
- debug:
var: _index
- debug:
var: l2
Upvotes: 2
Reputation: 603
In the end made jinja filter "natsort_filter.py" that does what I need. Get it here if you like:
https://gitlab.privatecloud.sk/vladoportos/custom-jinja-filters
It does require natsort module for python, but than it works just fine :)
Upvotes: 0