Ansible provide multiple ways that you can use to replace a string, an entire line or words that match a certain pattern. There are two modules that you can use to achieve this: the replace module and the inline module. We are going to dive deep and take a look at some examples of how these modules can be used in a playbook to replace strings and lines.
Replacing a string from a file with Ansible
The replace module replaces all instances of a defined string within a file.
If the string does not exist, then nothing will be done and no error will be displayed. Ansible simply returns that nothing has been changed. To successfully replace strings in a file, three parameters are required:
- The location of the file denoted by the ‘path‘ directive.
- The ‘regexp‘ directive – The string to be replaced or changed. Additionally, you can pass any regular Python expression.
- The ‘replace‘ directive – This is the replacement word or string.
This is how the syntax looks like with the replace module:
- replace:
path: /path/to/file
regexp: 'string or regular expression for search'
replace: 'word to replace the search string'
backup: yes
I have a sample text file called sample.txt which has the content below.
Unix is a free and opensource system used by developers, and desktop lovers. Thanks to Linux Torvalds’ efforts, Unix grew to become the most popular opensource system.
The goal is to replace the string ‘Unix’ with ‘Linux’. To achieve that, we are going to create a playbook file as shown.
- hosts: 127.0.0.1 tasks: - name: Ansible replace string example replace: path: /etc/ansible/sample.txt regexp: 'Unix' replace: "Linux"
We are then going to run the playbook.
# ansible-playbook sample.txt
From the output, you can clearly see that the string ‘Unix’ has been replaced by ‘Linux’
Let’s take another example.
Our second objective is to change a hostname entry in my /etc/hosts file from server.myubuntu.com to server.linuxtechi.info
We will create a playbook file change_hostname.yml which will look as follows:
- hosts: 127.0.0.1 tasks: - name: Ansible replace string example replace: path: /etc/hosts regexp: '(\s+)server\.myubuntu\.com(\s+.*)?$' replace: '\1server.linuxtechi.info\2'
Upon running the playbook, the name of the domain name changes accordingly as shown:
# ansible-playbook change_hostname.yml
Ansible lineinfile module
The Ansible inline module can be used in a variety of ways. It can be used for inserting a new line, removing or modifying an existing line from the file. We are going to take a closer look at each of these.
Inserting a line at the end of the file (EOF)
To start off, we will begin by learning how to create a line if it is not present in a file. Begin by specifying the path of the file where you are going to add the line using the path attribute. This has replaced the dest option which was used in Ansible 2.3 and earlier versions.
Then specify the line to be added at EOF. In this case, we’re adding a new entry to the /etc/hosts file. If the line already exists, then Ansible will skip adding it and no changes will be made.
The state parameter instructs Ansible to write the line in the file and the create parameter tells Ansible to create the file if it’s not already there. This is the update_ip.yml playbook file.
- hosts: 127.0.0.1 tasks: - name: Ansible update IP address lineinfile: path: /etc/hosts line: '173.82.56.150 wwww.linuxtechi.io' state: present create: yes
When the playbook file is run, notice that the new entry or line has been added.
# ansible-playbook update_ip.yml
Inserting a line before or after
Sometimes, you may want to insert a new line just before or after a section of a file and not always at the end of the line. For this, you need to use the insertafter and insertbefore directives.
In the playbook below, we are adding a line to specify our preferred inventory file just after the [defaults] section in the ansible.cfg file. We have escaped the [] since they are regex characters.
- hosts: 127.0.0.1 tasks: - name: Ansible update IP address lineinfile: path: /etc/ansible/ansible.cfg line: 'inventory = /home/linuxtechi/hosts' insertafter: '\[defaults\]'
To add a line just before a parameter, use the ‘insertbefore‘ parameter. In the example below, we are adding the same line just before the #library pattern in the Ansible config file.
- hosts: 127.0.0.1 tasks: - name: Ansible update IP address lineinfile: path: /etc/ansible/ansible.cfg line: 'inventory = /home/linuxtechi/hosts' insertbefore: ‘#library’
Remove a line using lineinfile module
This is the exact opposite of adding a line. A simple way of achieving this is to set the state parameter to absent . For example, to remove the entry in the file, ensure that the state parameter has the absent value
- hosts: 127.0.0.1 tasks: - name: Ansible update IP address lineinfile: path: /etc/hosts line: ‘173.82.56.150 wwwwlinuxtechi.io’ state: absent
Another way of removing a line is by using the regexp parameter. For example, the playbook below deletes all lines in a file beginning with the Unix word.
- hosts: 127.0.0.1 tasks: - name: Ansible lineinfile regexp example lineinfile: dest: /etc.ansible/sample.txt regexp: '^Unix' state: absent
That’s all from this article, I hope it helps to understand how to replace a string and lines with Ansible.
Also Read: 9 tee Command Examples in Linux
Good information.
What about if I want to replace a line if it exists and if the line does not exist then add the line to the bottom of the file ?
lineinfile does that by default, when using regex or search_string and state=present and you don’t specify insertbefore or insertafter.