Ansible Automation is really powerful with its filters and functions. It does provide various string manipulation and formatting filters from Jinja and Python.
In this article, we are going to see how to Split strings in Ansible.
As you might have already guessed, Ansible provides filters/functions to ease our job.
Ansible split
is a filter based on Python Split to split based on a character (separator)
We will see examples of Ansible Split filters with different datasets like Simple strings, Lists, Dictionaries etc.
Ansible Split Examples
When it comes to string formatting, Splitting the string into multiple parts based on the separator position has always been a key element.
Let's say you have a CSV file and you want to convert the CSV(comma separated values) into a list of values like sequence or array like this
sarav,9876543210,[email protected] =>to=> ['sarav','9876543210','[email protected]']
Now you can simply use their index value to get the value like name, mobile or email id
Or let's imagine you have a lot of business email IDs and you are interested in only the domain names
[email protected] [email protected] [email protected] [email protected]
With python, you can simply do it like this
Let us see how to do the same with Ansible now.
Not just one, There are multiple ways to do this in Ansible. here is one more
Let us go through the source code of these items and much more, to understand the Ansible Split filter better.
Quick Note on Supported Ansible Versions:
Ansible Split is a Jinja2 Filter and Legacy Ansible versions do not support Jinja2 and Jinja3 filters.
I recommend you to update the Ansible version if you are getting the following error
no filter named 'split'
I have used Ansible 2.10+ for testing all these Split filters.
Example1: Ansible Split Simple String
Splitting a simple string in Ansible with a Split filter is no big job.
All you need to use is a simple split followed by the string. Here is a quick example
--- - name: Ansible Split Examples hosts: localhost tasks: - name: Split Simple String Example debug: msg={{ '[email protected]'|split('@')}}
Here is the execution and the output
I know this is a really simple example. Move on to some real-time examples down below.
Example2: Ansible Split with loop - To process list of strings
In this example, we have a list of email IDs stored in a variable called emails
which is being sent to the loop
iteration
For those who are familiar with with_items
you can use that too. Each element on the list can be accessed by the variable item
the item
variable is being used within the debug msg
statement where we are applying the split
across each email ID
The result of the split would be a list with two items. which can be accessed using Ansible special filters first
and last
first
is to get the first element of the list more likelist[0]
last
is to get the last element of the list more likelist[-1]
orlist[len(list)-1]
In our case, we know prior that there would be only two values in the returned list of split. so we can use the last
here to get the domain names as our seperator
is @
--- - name: Ansible Split Examples hosts: localhost vars: - emails: ['[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]'] tasks: - name: print only domain Names from Email IDs with Split debug: msg="{{ item | split('@') | last }}" loop: "{{emails}}"
Example3: Ansible Split with Map - To process Nested Lists
Here is the source code of the second playbook
--- - name: Ansible Split Examples hosts: localhost vars: - emails: ['[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]'] tasks: - name: print only domain names from Email IDs with Split debug: msg={{ emails | map('split','@') | flatten | select('match','.+\..+$') }}
The reason we are using the map
filter here is that we want to apply the split
function on the elements of the list. not on the list itself.
If it is a simple string that we want to split we can simply do it like this
msg: "{{ '[email protected]' | split('@') | last }}"
but our email ids are stored inside the list and in our last example, we have iterated over the list emails
and passed each email id to for the split processing with item
Now instead of using loop
we are using Ansible Map filter
To know more about the Ansible map refer to our dedicated article here.
flatten
is used here to convert the list of lists ( nested lists ) into a single list.
Ideally, the result of the map and split would be like this, [[],[],[],[]]
a Nested list/array
"msg": [ [ "hello", "gritfy.com" ], [ "steve", "google.com" ], [ "mark", "ibm.com" ], [ "dave", "meta.com" ], [ "admin", "gritfy.in" ] ] }
and with flatten
it would become like this, A single list with multiple values.
"msg": [ "hello", "gritfy.com", "steve", "google.com", "mark", "ibm.com", "dave", "meta.com", "admin", "gritfy.in" ]
Now our job is to get the elements matching a regex pattern *.[org|com]
etc. That's, where we are using select
select
is a jinja2 filter that helps us to select the matching item from the list, with select
we are going to apply another filter named match
to perform the regular expression pattern matching.
Our regular expression is this .+\..+$
to select the domain from the list. you can try this pattern in regex101.com to find out what it does ( if you are new to regex)
The result of this second playbook would be like this
Much simpler and neat. everything is done in a single line with no loop.
Example4: Ansible Split - With File Content
As part of this example, we are going to read a file named /etc/passwd
from the filesystem and process it line by line and split based on separator
--- - name: Ansible Split Examples hosts: localhost vars: - usernames : [] tasks: - name: print only domain names from Email IDs with Split set_fact: usernames: '{{ usernames + [ item | split(":") | first ] }}' loop: "{{ lookup('file', '/etc/passwd').splitlines() | select('match','^(?!#)')}}" - debug: var=usernames
we have used a few functions/filters here, let us decode each one of them
to begin with, let us start with loop
expression
"{{ lookup('file', '/etc/passwd').splitlines() | select('match','^(?!#)')}}"
Here the
lookup
filter is used to read the content of the filessplitlines
is to split the file content line by lineselect
filter to execute another filter to select a matching element from the sequence. ( it is different from selectattr)match
a filter being executed by select. to perform regular expression matching
Here is the output of this playbook.
Conclusion
In this detailed article about Ansible Split. I tried to cover not just the simple split but also to cover how can you use it with dist, List etc
we have also talked about various other filters and topics like
- How to read a file content into Ansible split into lines
- Selecting elements from the LIST using
select
- Regular expression pattern matching using
match
- How to use
loop
and iteration statements - How to use expressions with
loop
etc.
Hope you would find this article helpful.
Cheers
Sarav AK
Follow me on Linkedin My Profile Follow DevopsJunction onFacebook orTwitter For more practical videos and tutorials. Subscribe to our channel
Signup for Exclusive "Subscriber-only" Content