# Complex lineinfile/replace

**URL:** <https://forum.ansible.com/t/complex-lineinfile-replace/37281>\
**Category:** Ansible Project\
**Created:** [October 31, 2022, 5:47pm UTC](https://forum.ansible.com/t/complex-lineinfile-replace/37281 "2022-10-31T17:47:32Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Cy\_Schubert](https://avatars.discourse-cdn.com/v4/letter/c/f1d935/32.png) [@Cy\_Schubert](https://forum.ansible.com/u/Cy_Schubert)\
**Post date:** [October 31, 2022, 5:47pm UTC](https://forum.ansible.com/t/complex-lineinfile-replace/37281/1 "2022-10-31T17:47:32Z")

</div>

I need to replace lines in /etc/fstab using the following logic:

if line contains “ext4”; then  
if line ends in “0 0”; then  
replace “0 0” with “1 2”

I can easily do this with sed:  
sed ‘/ext4/s/0 0$/1 2/’

But from what I can tell the lineinfile and replace modules accept only one regexp, not two. How would I do this in ansible without using the script or command modules?

---

<div class="post-metadata">

**Author:** ![Walter\_Rowe](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/walter_rowe/32/4506_2.png) [@Walter\_Rowe](https://forum.ansible.com/u/Walter_Rowe)\
**Post date:** [October 31, 2022, 6:03pm UTC](https://forum.ansible.com/t/complex-lineinfile-replace/37281/2 "2022-10-31T18:03:40Z")

</div>

[https://docs.ansible.com/ansible/latest/collections/ansible/builtin/lineinfile\_module.html](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/lineinfile_module.html)

```auto
# See [https://docs.python.org/3/library/re.html](https://docs.python.org/3/library/re.html) for further details on syntax
- name: Use backrefs with alternative group syntax to avoid conflicts with variable values
  ansible.builtin.lineinfile:
    path: /tmp/config
    regexp: ^(host=).*
    line: \g<1>{{ hostname }}
    backrefs: yes

```

Can you use backrefs to incorporate part of the found regexp in the new line?

ansible.builtin.lineinfile:  
path: /etc/fstab  
**backrefs: yes**  
regexp: “(ext4._)\s+0 0\s_$”  
line: “\g\<1\> 1 2”

Just a stab in the dark. Have not tested this code.

Walter

---

<div class="post-metadata">

**Author:** ![Walter\_Rowe](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/walter_rowe/32/4506_2.png) [@Walter\_Rowe](https://forum.ansible.com/u/Walter_Rowe)\
**Post date:** [October 31, 2022, 6:08pm UTC](https://forum.ansible.com/t/complex-lineinfile-replace/37281/3 "2022-10-31T18:08:19Z")

</div>

Actually a little more improvement to get the whole line from the regex minus the “0 0” tail.

> ansible.builtin.lineinfile:  
> path: /etc/fstab  
> **backrefs: yes**  
> regexp: “^(._ext4._)\s+0 0\s\*$”  
> line: “\g\<1\> 1 2”

Walter

---

<div class="post-metadata">

**Author:** ![Cy\_Schubert](https://avatars.discourse-cdn.com/v4/letter/c/f1d935/32.png) [@Cy\_Schubert](https://forum.ansible.com/u/Cy_Schubert)\
**Post date:** [October 31, 2022, 9:08pm UTC](https://forum.ansible.com/t/complex-lineinfile-replace/37281/4 "2022-10-31T21:08:53Z")

</div>

Ahh yes, python regular expressions. Thank you.

---

<div class="post-metadata">

**Author:** ![Cy\_Schubert](https://avatars.discourse-cdn.com/v4/letter/c/f1d935/32.png) [@Cy\_Schubert](https://forum.ansible.com/u/Cy_Schubert)\
**Post date:** [November 1, 2022, 5:03pm UTC](https://forum.ansible.com/t/complex-lineinfile-replace/37281/5 "2022-11-01T17:03:24Z")

</div>

Managed to get it working. It only affects the last matched instance in the file. Would the replace module be a better choice?

---

<div class="post-metadata">

**Author:** ![Walter\_Rowe](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/walter_rowe/32/4506_2.png) [@Walter\_Rowe](https://forum.ansible.com/u/Walter_Rowe)\
**Post date:** [November 1, 2022, 6:15pm UTC](https://forum.ansible.com/t/complex-lineinfile-replace/37281/6 "2022-11-01T18:15:36Z")

</div>

Yes, replace would be better if you have multiple instances in a file and want to modify all of them.

[https://docs.ansible.com/ansible/latest/collections/ansible/builtin/replace\_module.html](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/replace_module.html)

Walter

---

<div class="post-metadata">

**Author:** ![Walter\_Rowe](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/walter_rowe/32/4506_2.png) [@Walter\_Rowe](https://forum.ansible.com/u/Walter_Rowe)\
**Post date:** [November 1, 2022, 6:19pm UTC](https://forum.ansible.com/t/complex-lineinfile-replace/37281/7 "2022-11-01T18:19:49Z")

</div>

ansible.builtin.replace:  
path: /etc/fstab  
regexp: “^(._ext4._)\s+0 0\s\*$”  
replace: “\g\<1\> 1 2”

Walter

---

<div class="post-metadata">

**Author:** ![shearn](https://avatars.discourse-cdn.com/v4/letter/s/ba8739/32.png) [@shearn](https://forum.ansible.com/u/shearn)\
**Post date:** [November 1, 2022, 6:36pm UTC](https://forum.ansible.com/t/complex-lineinfile-replace/37281/8 "2022-11-01T18:36:54Z")

</div>

It needs to be ‘whitespace’ext4’whitespace’ unless you want to change mount points that might contain the letters ext4.

Are you sure you want to change the root filesystem to ‘1 2’

Man Page: The root filesystem should be specified with a fs\_passno of 1

Regards,

Stan

---

<div class="post-metadata">

**Author:** ![Walter\_Rowe](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/walter_rowe/32/4506_2.png) [@Walter\_Rowe](https://forum.ansible.com/u/Walter_Rowe)\
**Post date:** [November 1, 2022, 6:38pm UTC](https://forum.ansible.com/t/complex-lineinfile-replace/37281/9 "2022-11-01T18:38:32Z")

</div>

Good catch!

ansible.builtin.replace:  
&nbsp;&nbsp;path: /etc/fstab  
&nbsp;&nbsp;regexp: "^(.\*\s+ext4\s+.\*)\s+0 0\s\*$"  
&nbsp;&nbsp;replace: "\g\<1\> 1 2"

Walter

---

<div class="post-metadata">

**Author:** ![shearn](https://avatars.discourse-cdn.com/v4/letter/s/ba8739/32.png) [@shearn](https://forum.ansible.com/u/shearn)\
**Post date:** [November 1, 2022, 7:06pm UTC](https://forum.ansible.com/t/complex-lineinfile-replace/37281/10 "2022-11-01T19:06:43Z")

</div>

Thank you, Walter. I always enjoy reading your solutions.

This is where exactness matters and can become a rabbit hole very quickly depending on how much of your environment is a wild wild west.

SUCCENCT DEFINITION: The match should be the 3rd argument (ARG3) in /etc/fstab equal to “ext4” of any lines not beginning with “#” with ARG5 and ARG6 = “0”.

Depending on the risk you’re willing to accept, /etc/fstab has six white-space delimited arguments.

ARG1\s+ARG2\s+ARG3\s+ARG4\s+ARG5\s+ARG6

When ARG3 = ext4 and ARG5 and ARG6 = 0

then

ARG1 ARG2 ext4 ARG4 1 2

backrefs will help keep it straight.

regexp: “^(._)\s+(._)\s+ext4\s+(0)\s+(0)$”

replace: “\1 \2 ext4 \4 1 2”

Do you agree this is more exact and better declaratively? Probably way more than Cy Schubert really wanted.

Regards,

Stan

---

<div class="post-metadata">

**Author:** ![Walter\_Rowe](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/walter_rowe/32/4506_2.png) [@Walter\_Rowe](https://forum.ansible.com/u/Walter_Rowe)\
**Post date:** [November 1, 2022, 7:12pm UTC](https://forum.ansible.com/t/complex-lineinfile-replace/37281/11 "2022-11-01T19:12:15Z")

</div>

You have to test it. The regex wants to match the longest string possible and .\* matches everything. If the regex I typed works, go with it. You can overthink it and spend cycles trying to get something to work when a simpler regex might have been sufficient.

Walter
