Ansible split Filter: Split Strings into Lists (Complete Guide)
By Luca Berton · Published 2026-04-03 · Category: troubleshooting
How to split strings into lists with Ansible split filter. Split by delimiter, whitespace, regex. Convert CSV to lists, parse output.
The split filter in Ansible (Jinja2) divides a string into a list of substrings based on a delimiter. It's essential for parsing command output, configuration files, and structured text.
Basic Split
- name: Split a comma-separated string
ansible.builtin.debug:
msg: "{{ 'apple,banana,cherry' | split(',') }}"
# Output: ['apple', 'banana', 'cherry']
See also: Ansible regex_search Filter: Search Strings with Regex Patterns (Guide)
Split with Different Delimiters
# Split by space
- debug:
msg: "{{ 'hello world foo' | split(' ') }}"
# ['hello', 'world', 'foo']
# Split by newline
- debug:
msg: "{{ multiline_var | split('\n') }}"
# Split by colon (passwd-style)
- debug:
msg: "{{ 'root:x:0:0:root:/root:/bin/bash' | split(':') }}"
# ['root', 'x', '0', '0', 'root', '/root', '/bin/bash']
# Split by multiple characters
- debug:
msg: "{{ 'key=value' | split('=') }}"
# ['key', 'value']
Limit Number of Splits
- name: Split only first occurrence
debug:
msg: "{{ 'key=value=extra' | split('=', 1) }}"
# ['key', 'value=extra']
See also: Ansible Split String: Filter Guide for CSV, Delimiters & Lists
Split Command Output
- name: Get disk usage
ansible.builtin.command: df -h /
register: df_output
- name: Parse disk usage
ansible.builtin.set_fact:
disk_usage: "{{ df_output.stdout_lines[1].split() }}"
# disk_usage[4] = usage percentage like '45%'
Combine split with Other Filters
Split and select
- name: Get username from email
debug:
msg: "{{ 'user@example.com' | split('@') | first }}"
# 'user'
Split and join (replace)
- name: Replace dashes with underscores
debug:
msg: "{{ 'my-variable-name' | split('-') | join('_') }}"
# 'my_variable_name'
Split and filter empty strings
- name: Handle multiple delimiters
debug:
msg: "{{ ' hello world ' | split(' ') | reject('equalto', '') | list }}"
# ['hello', 'world']
See also: Ansible from_json & to_json Filters: Parse & Convert JSON (Guide)
Parse Key-Value Pairs
- name: Parse config line
ansible.builtin.set_fact:
config_key: "{{ 'max_connections = 100' | split('=') | first | trim }}"
config_value: "{{ 'max_connections = 100' | split('=') | last | trim }}"
Split vs regex_findall
For complex patterns, use regex_findall instead:
# Extract all numbers from a string
- debug:
msg: "{{ 'server1:8080, server2:9090' | regex_findall('\d+') }}"
# ['1', '8080', '2', '9090']
# Extract IP addresses
- debug:
msg: "{{ log_line | regex_findall('\d+\.\d+\.\d+\.\d+') }}"
Practical Examples
Parse /etc/hosts
- name: Read hosts file
ansible.builtin.slurp:
path: /etc/hosts
register: hosts_file
- name: Parse host entries
ansible.builtin.set_fact:
host_entries: >-
{{ (hosts_file.content | b64decode).split('\n')
| reject('match', '^#')
| reject('equalto', '')
| map('split', None, 1)
| list }}
Parse CSV data
- name: Process CSV line
ansible.builtin.debug:
msg: "Name: {{ item.split(',')[0] }}, Age: {{ item.split(',')[1] }}"
loop:
- "Alice,30"
- "Bob,25"
FAQ
What happens if the delimiter isn't found?
The split filter returns a list with the original string as the only element: "hello" | split(",") → ["hello"].
How do I split by whitespace (any amount)?
Use split() without arguments — it splits on any whitespace and removes empty strings: " a b c " | split() → ["a", "b", "c"].
Can I split into a fixed number of parts?
Yes, use the maxsplit parameter: "a-b-c-d" | split("-", 2) → ["a", "b", "c-d"].
Basic Split
- vars:
csv_line: "web1,web2,web3,db1"
debug:
msg: "{{ csv_line.split(',') }}"
# ['web1', 'web2', 'web3', 'db1']
Split with Filter Syntax
- debug:
msg: "{{ 'hello world' | split(' ') }}"
# ['hello', 'world']
- debug:
msg: "{{ '/var/log/nginx/access.log' | split('/') }}"
# ['', 'var', 'log', 'nginx', 'access.log']
Split Command Output
- command: "df -h / | tail -1"
register: disk
changed_when: false
- set_fact:
disk_usage: "{{ disk.stdout.split() }}"
# ['/dev/sda1', '50G', '25G', '25G', '50%', '/']
- debug:
msg: "Disk usage: {{ disk_usage[4] }}"
# 50%
Split Multi-Line Text
- vars:
hosts_content: |
192.168.1.10 web1
192.168.1.11 web2
192.168.1.20 db1
debug:
msg: "{{ hosts_content.strip().split('\n') }}"
Parse CSV Data
- vars:
csv_data: "name,email,role\nalice,alice@co.com,admin\nbob,bob@co.com,user"
set_fact:
users: >-
{{ csv_data.split('\n')[1:] | map('split', ',') |
map('zip', ['name', 'email', 'role']) |
map('map', 'reverse') | map('community.general.dict') | list }}
Simpler approach:
- vars:
line: "alice,alice@example.com,admin"
fields: "{{ line.split(',') }}"
debug:
msg: "User: {{ fields[0] }}, Email: {{ fields[1] }}, Role: {{ fields[2] }}"
Split with Limit
- debug:
msg: "{{ 'one:two:three:four'.split(':', 2) }}"
# ['one', 'two', 'three:four'] — splits at most 2 times
Related String Operations
| Operation | Syntax | Result |
|-----------|--------|--------|
| Split | 'a,b,c' | split(',') | ['a','b','c'] |
| Join | ['a','b'] | join(',') | 'a,b' |
| Replace | 'hello' | replace('l','r') | 'herro' |
| Regex split | 'a1b2c' | regex_findall('[a-z]+') | ['a','b','c'] |
| First element | 'a/b/c'.split('/') | first | 'a' |
| Last element | 'a/b/c'.split('/') | last | 'c' |
Extract from Structured Strings
# Parse "key=value" pairs
- vars:
config_line: "server=db.example.com port=5432 name=mydb"
set_fact:
config: "{{ dict(config_line.split() | map('split', '=')) }}"
# {server: db.example.com, port: '5432', name: mydb}
FAQ
split vs regex_findall?
split divides by a fixed delimiter. regex_findall extracts matches by pattern:
# Split by comma
"a,b,c".split(',') → ['a', 'b', 'c']
# Extract numbers
"age:25 score:98" | regex_findall('\d+') → ['25', '98']
How do I split and pick the Nth element?
msg: "{{ 'path/to/file.txt'.split('/')[-1] }}"
# file.txt (last element)
Can I split by multiple delimiters?
Use regex: "a,b;c" | regex_findall('[^,;]+')
Basic Split
- vars:
csv_line: "alice,bob,charlie,dave"
debug:
msg: "{{ csv_line.split(',') }}"
# ["alice", "bob", "charlie", "dave"]
Split by Different Delimiters
# Colon (PATH-style)
- debug:
msg: "{{ '/usr/bin:/usr/local/bin:/home/user/bin'.split(':') }}"
# Space
- debug:
msg: "{{ 'one two three'.split() }}"
# Newlines
- debug:
msg: "{{ multiline_output.split('\n') }}"
# Pipe
- debug:
msg: "{{ 'field1|field2|field3'.split('|') }}"
# Multiple characters
- debug:
msg: "{{ 'key=value'.split('=') }}"
Split with Limit
# Split only first N times
- vars:
line: "key=value=with=equals"
debug:
msg: "{{ line.split('=', 1) }}"
# ["key", "value=with=equals"]
Split Command Output
- command: df -h /
register: disk_result
- set_fact:
disk_usage: "{{ disk_result.stdout_lines[1].split() }}"
# ["dev/sda1", "50G", "23G", "27G", "46%", "/"]
- debug:
msg: "Disk usage: {{ disk_usage[4] }}"
# "46%"
Split and Select
# Get filename from path
- vars:
filepath: "/var/log/myapp/error.log"
debug:
msg: "{{ filepath.split('/')[-1] }}"
# "error.log"
# Get directory
- debug:
msg: "{{ filepath.split('/')[:-1] | join('/') }}"
# "/var/log/myapp"
# Get file extension
- debug:
msg: "{{ filepath.split('.')[-1] }}"
# "log"
# Get domain from email
- vars:
email: "user@example.com"
debug:
msg: "{{ email.split('@')[1] }}"
# "example.com"
Split + Loop
- vars:
allowed_ips: "10.0.1.1,10.0.1.2,10.0.1.3"
ansible.builtin.iptables:
chain: INPUT
source: "{{ item }}"
jump: ACCEPT
loop: "{{ allowed_ips.split(',') }}"
become: true
Split + Filter
# Split and remove empty strings
- vars:
messy: "one,,two,,,three"
debug:
msg: "{{ messy.split(',') | select() | list }}"
# ["one", "two", "three"]
# Split, trim, and sort
- vars:
tags: " web , api , database , cache "
debug:
msg: "{{ tags.split(',') | map('trim') | sort | list }}"
# ["api", "cache", "database", "web"]
Split Multiline Output
- shell: cat /etc/passwd
register: passwd
- set_fact:
users: "{{ passwd.stdout_lines | map('regex_replace', ':.*', '') | list }}"
# Extracts usernames from each line
Parse Key=Value Pairs
- vars:
env_string: "DB_HOST=localhost DB_PORT=5432 DB_NAME=mydb"
set_fact:
env_dict: "{{ dict(env_string.split() | map('split', '=') | list) }}"
# {"DB_HOST": "localhost", "DB_PORT": "5432", "DB_NAME": "mydb"}
Join (Reverse of Split)
- vars:
items: ["one", "two", "three"]
debug:
msg: "{{ items | join(', ') }}"
# "one, two, three"
# Split and rejoin with different delimiter
- vars:
path: "one/two/three"
debug:
msg: "{{ path.split('/') | join('.') }}"
# "one.two.three"
Related Filters
| Filter | Purpose |
|--------|---------|
| split() | String → List |
| join() | List → String |
| regex_replace | Pattern replacement |
| trim | Remove whitespace |
| map('split') | Split each item in list |
| select | Filter empty items |
FAQ
split vs splitlines?
split('\n') and splitlines() are similar, but splitlines() handles \r\n and other line endings. For command output, use stdout_lines (already split).
How to split by regex?
Use regex_findall instead:
msg: "{{ 'one2two3three' | regex_findall('[a-z]+') }}"
# ["one", "two", "three"]
Can I split and get the Nth element in one expression?
Yes: "{{ mystring.split(',')[2] }}" gets the third element.
Related Articles
• rendering Jinja2 templates with Ansible • Ansible Multiline Strings Guide • chdir option in Ansible command • Ansible Loops Guide • Ansible Split Filter GuideCategory: troubleshooting