Introduction

Jinja2 string filters in Ansible transform text in variables, templates, and task parameters — uppercase, lowercase, title case, replace, regex, and more. These filters work everywhere Jinja2 expressions are used: playbooks, templates, and inventory variables.

Case Transformation Filters

upper — Convert to Uppercase

- name: Uppercase example
  ansible.builtin.debug:
    msg: "{{ 'hello world' | upper }}"
# Output: HELLO WORLD

lower — Convert to Lowercase

- name: Lowercase example
  ansible.builtin.debug:
    msg: "{{ 'Hello World' | lower }}"
# Output: hello world

capitalize — First Letter Uppercase

- name: Capitalize example
  ansible.builtin.debug:
    msg: "{{ 'hello world' | capitalize }}"
# Output: Hello world

title — Title Case

- name: Title case example
  ansible.builtin.debug:
    msg: "{{ 'hello world of ansible' | title }}"
# Output: Hello World Of Ansible

String Manipulation Filters

replace

- name: Replace text
  ansible.builtin.debug:
    msg: "{{ 'Hello World' | replace('World', 'Ansible') }}"
# Output: Hello Ansible

regex_replace

- name: Regex replace
  ansible.builtin.debug:
    msg: "{{ 'server-01.example.com' | regex_replace('^server-(\\d+)\\..*', 'srv-\\1') }}"
# Output: srv-01
- name: Extract version number
  ansible.builtin.debug:
    msg: "{{ 'ansible-core 2.16.0' | regex_search('(\\d+\\.\\d+\\.\\d+)') }}"
# Output: 2.16.0

Whitespace and Formatting

trim

- name: Remove whitespace
  ansible.builtin.debug:
    msg: "'{{ '  hello  ' | trim }}'"
# Output: 'hello'

center / ljust / rjust (in templates)

{{ 'hello' | center(20) }}
{{ 'hello' | ljust(20) }}
{{ 'hello' | rjust(20) }}

wordwrap

- name: Wrap long text
  ansible.builtin.debug:
    msg: "{{ long_text | wordwrap(60) }}"

truncate

- name: Truncate text
  ansible.builtin.debug:
    msg: "{{ 'This is a very long description' | truncate(20) }}"
# Output: This is a very lo...

Practical Examples

Normalize Hostnames

- name: Set normalized hostname
  ansible.builtin.hostname:
    name: "{{ custom_hostname | lower | replace(' ', '-') | regex_replace('[^a-z0-9-]', '') }}"

Generate Config from Variables

vars:
  app_name: "My Application"
  environment: "production"

tasks:
  - name: Generate env file
    ansible.builtin.copy:
      content: |
        APP_NAME={{ app_name | upper | replace(' ', '_') }}
        ENVIRONMENT={{ environment | upper }}
        LOG_LEVEL={{ 'DEBUG' if environment == 'development' else 'INFO' }}
      dest: /etc/myapp/.env

Dynamic File Paths

- name: Create log directory per environment
  ansible.builtin.file:
    path: "/var/log/{{ app_name | lower | replace(' ', '-') }}/{{ env | lower }}"
    state: directory

Conditional Formatting in Templates

{# nginx.conf.j2 #}
server {
    server_name {{ domain | lower }};
    root /var/www/{{ domain | lower | replace('.', '_') }};

    {% for header_name, header_value in custom_headers.items() %}
    add_header {{ header_name | title | replace('_', '-') }} "{{ header_value }}";
    {% endfor %}
}

Sanitize User Input

- name: Create user from input
  ansible.builtin.user:
    name: "{{ requested_username | lower | regex_replace('[^a-z0-9_-]', '') | truncate(32, true, '') }}"
    state: present

Complete Filter Reference

FilterInputOutput
upperhelloHELLO
lowerHELLOhello
capitalizehello worldHello world
titlehello worldHello World
replace('a','b')catcbt
regex_replacePattern-based replace—
regex_searchExtract match—
trim hi hi
truncate(10)long text herelong te...
wordwrap(40)Long textWrapped text
lengthhello5
reversehelloolleh
split('.')a.b.c['a','b','c']
join('-')['a','b']a-b
default('x')undefinedx
b64encodehelloaGVsbG8=
b64decodeaGVsbG8=hello
hash('sha256')helloSHA256 hex
urlencodehello worldhello%20world
quoteShell-unsafe stringShell-safe

Chaining Filters

# Multiple filters in sequence
msg: "{{ raw_input | trim | lower | replace(' ', '_') | truncate(32, true, '') }}"

# With default for undefined variables
msg: "{{ hostname | default('localhost') | upper }}"

Conclusion

Use | upper for uppercase, | lower for lowercase, | replace for simple substitutions, and | regex_replace for pattern-based transformations. Chain filters for complex operations like | trim | lower | replace(' ', '-'). All Jinja2 string filters work in playbooks, templates, and inventory variables. The complete filter list is in the Jinja2 documentation.