Replace Strings and Lines with Ansible Replace Module
The Ansible replace module is designed to handle simple and complex text substitutions in files. It's particularly useful when you need to make consistent changes across multiple systems or files. The module allows you to search for a string or a pattern and replace it with a new value.
Here are some of the key features of Ansible replace module:
- Idempotency: Ensures the change is made only if necessary.
- Flexibility: Supports regular expressions for advanced text matching.
- Simplicity: Easy to use with straightforward parameters.
In this tutorial, we'll explore how to use the Ansible replace module to modify strings and lines in files.
Basic Syntax
Let's look at the basic syntax of the replace module:
- name: Replace a string in a file
ansible.builtin.replace:
path: /path/to/file
regexp: 'old_string'
replace: 'new_string'
This Ansible playbook search for a specific string, old_string
in a file located at /path/to/file
and replace it with a new string, \new_string
. It uses the replace module from Ansible's built-in library to perform this string replacement. The task ensures that every occurrence of old_string
in the specified file is replaced with new_string
.
Replacing a Simple String
Suppose you have a configuration file where you need to replace localhost
with 127.0.0.1
. Here’s how you can achieve this:
Create a playbook with the following content:
---
- name: Replace localhost with 127.0.0.1
hosts: all
tasks:
- name: Replace localhost with 127.0.0.1
ansible.builtin.replace:
path: /etc/example.conf
regexp: 'localhost'
replace: '127.0.0.1'
Explanation:
path
: Specifies the file to modify.regexp
: The pattern to search for (in this case, localhost).replace
: The new value to substitute (127.0.0.1).
Now, run the above playbook.
ansible-playbook replace_string.yml
Ansible will display a summary of changes made. If localhost was found and replaced, it will show that the task has changed.
PLAY [Replace localhost with 127.0.0.1] ****************************************
TASK [Gathering Facts] *********************************************************
ok: [hostname]
TASK [Replace localhost with 127.0.0.1] ****************************************
changed: [hostname]
PLAY RECAP *********************************************************************
hostname : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Changing a Specific Line
Imagine you need to update the port number in a configuration file from 8080
to 9090
.
Let's create a playbook and add the following content:
---
- name: Replace port number in configuration file
hosts: all
tasks:
- name: Replace port 8080 with 9090
ansible.builtin.replace:
path: /etc/example.conf
regexp: '^port=8080'
replace: 'port=9090'
Explanation:
regexp
: The pattern^port=8080
ensures we only match lines that start withport=8080
.
Now, run the above playbook.
ansible-playbook replace_port.yml
Ansible will update the port number and indicate that the task has changed.
PLAY [Replace port number in configuration file] *******************************
TASK [Gathering Facts] *********************************************************
ok: [hostname]
TASK [Replace port 8080 with 9090] *********************************************
changed: [hostname]
PLAY RECAP *********************************************************************
hostname : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Using Regular Expressions for Advanced Replacements
Suppose you need to replace any occurrence of version 1.0
with version 2.0
, regardless of its position in the file.
Create a playbook with the following content:
---
- name: Replace version number using regex
hosts: all
tasks:
- name: Replace version 1.0 with version 2.0
ansible.builtin.replace:
path: /etc/example.conf
regexp: 'version\s+1\.0'
replace: 'version 2.0'
Explanation:
regexp
: The patternversion\s+1\.0
matchesversion 1.0
with any amount of whitespace in between.
Now, run the above playbook.
ansible-playbook replace_version.yml
Ansible will replace all instances of version 1.0
with version 2.0
.
PLAY [Replace version number using regex] **************************************
TASK [Gathering Facts] *********************************************************
ok: [hostname]
TASK [Replace version 1.0 with version 2.0] ************************************
changed: [hostname]
PLAY RECAP *********************************************************************
hostname : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Replacing a String with Backup
Sometimes you want to ensure that the original file is preserved before making changes. For example, if the replacement string already exists, you can use the backup
parameter to ensure the original file is preserved before changes are made.
- name: Replace with backup
ansible.builtin.replace:
path: /etc/example.conf
regexp: 'old_string'
replace: 'new_string'
backup: yes
Now, run the above playbook.
ansible-playbook idempotency_backup.yml
You will see the following output.
PLAY [Replace with backup] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [hostname]
TASK [Replace old_string with new_string with backup] **************************
changed: [hostname]
PLAY RECAP *********************************************************************
hostname : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Replacing a Multiline Pattern
In some cases, you might need to replace a block of text spanning multiple lines. Here's how you can handle multiline replacements.
Create a playbook with the following content.
- name: Replace a multiline pattern
hosts: all
tasks:
- name: Replace multiline text
ansible.builtin.replace:
path: /etc/example.conf
regexp: 'START_PATTERN.*?END_PATTERN'
replace: 'NEW_PATTERN'
backup: yes
Explanation:
regexp
: The patternSTART_PATTERN.*?END_PATTERN
matches any text betweenSTART_PATTERN
andEND_PATTERN
.replace
: Substitutes the matched text withNEW_PATTERN
.
Now, run this playbook.
ansible-playbook replace_multiline.yml
You will see the following output.
PLAY [Replace a multiline pattern] *********************************************
TASK [Gathering Facts] *********************************************************
ok: [hostname]
TASK [Replace multiline text] **************************************************
changed: [hostname]
PLAY RECAP *********************************************************************
hostname : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Case-Insensitive Replacement
If you need to perform a case-insensitive replacement, you can use the ignorecase
parameter.
Let's create a playbook.
- name: Case-insensitive replacement
hosts: all
tasks:
- name: Replace case-insensitive text
ansible.builtin.replace:
path: /etc/example.conf
regexp: 'caseInsensitivePattern'
replace: 'newPattern'
backup: yes
ignorecase: yes
Explanation:
ignorecase
: This parameter makes the replacement case-insensitive.
Now, run the above playbook.
ansible-playbook replace_case_insensitive.yml
You will see the following output.
PLAY [Case-insensitive replacement] ********************************************
TASK [Gathering Facts] *********************************************************
ok: [hostname]
TASK [Replace case-insensitive text] *******************************************
changed: [hostname]
PLAY RECAP *********************************************************************
hostname : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Conclusion
In this article, we explored the Ansible replace module and its practical applications. We covered how to replace simple strings, change specific lines, use regular expressions for advanced text manipulations, create backups, handle multiline patterns, and perform case-insensitive replacements.
If you are new to Ansible and want to learn it from scratch, our Ansible tutorial series will be of great help. It's written for RHCE exam but it helps you the same whether you are preparing for the exam or not.