# lineinfile task that spans multiple lines

**URL:** <https://forum.ansible.com/t/lineinfile-task-that-spans-multiple-lines/14512>\
**Category:** Ansible Project\
**Created:** [February 6, 2014, 8:02pm UTC](https://forum.ansible.com/t/lineinfile-task-that-spans-multiple-lines/14512 "2014-02-06T20:02:58Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jeff\_Geerling](https://avatars.discourse-cdn.com/v4/letter/j/13edae/32.png) [@Jeff\_Geerling](https://forum.ansible.com/u/Jeff_Geerling)\
**Post date:** [February 6, 2014, 8:02pm UTC](https://forum.ansible.com/t/lineinfile-task-that-spans-multiple-lines/14512/1 "2014-02-06T20:02:58Z")

</div>

I’m trying to make my lineinfile command that uses multiple lines idempotent:

- lineinfile: \>  
dest=/etc/example.conf  
regexp=‘^[test(.\*)’  
line=‘[test]{{ ‘\n’ }}secondline’

I’ve tried this, and the following regexp variations:

regexp=‘’/^[test(.\*)/s’ # trying to get it to work multiline  
regexp=‘^[test]{{ ‘\n’ }}secondline’ # trying to use same pattern in ‘line’

I’ve also tried a bunch of other variations, with no luck, as well as adding ‘insertafter=EOF’. In all cases, I ended up getting another block of text each time I ran ansible-playbook.

How can I do a lineinfile with multiple lines with idempotence?

(Also, I can’t get the line to work without wrapping newlines, tab characters, etc. in a variable reference ({{ }}), though I’ve seen other examples online where those whitespace characters must be working correctly.

---

<div class="post-metadata">

**Author:** ![Walid](https://avatars.discourse-cdn.com/v4/letter/w/ea5d25/32.png) [@Walid](https://forum.ansible.com/u/Walid)\
**Post date:** [February 7, 2014, 3:57am UTC](https://forum.ansible.com/t/lineinfile-task-that-spans-multiple-lines/14512/2 "2014-02-07T03:57:27Z")

</div>

The one way i know of is either just use shell/command and use sed, or break this into tasks, the first counts and registers the line needs to be replaced again using shell/cmd “grep”, and the second does the lineinfile per item using “with\_sequence” and remember to add +1 to the number counted as sequence does not accept 0 count

This was mentioned before in the list

---

<div class="post-metadata">

**Author:** ![Jeff\_Geerling](https://avatars.discourse-cdn.com/v4/letter/j/13edae/32.png) [@Jeff\_Geerling](https://forum.ansible.com/u/Jeff_Geerling)\
**Post date:** [February 8, 2014, 9:17pm UTC](https://forum.ansible.com/t/lineinfile-task-that-spans-multiple-lines/14512/3 "2014-02-08T21:17:18Z")

</div>

Is there any way to make lineinfile work with Python’s multiline regex (like /pattern/s)? lineinfile makes the idempotence a bit easier than grep/sed. But I’ll go that route if need be. Usually, I just use a template file anyways, but for this particular file, there are just three lines that need replacing, and the config file is pretty long.

---

<div class="post-metadata">

**Author:** ![Jeff\_Geerling](https://avatars.discourse-cdn.com/v4/letter/j/13edae/32.png) [@Jeff\_Geerling](https://forum.ansible.com/u/Jeff_Geerling)\
**Post date:** [February 10, 2014, 3:20pm UTC](https://forum.ansible.com/t/lineinfile-task-that-spans-multiple-lines/14512/4 "2014-02-10T15:20:12Z")

</div>

Another option that would work for ini-style files:

- ini\_file:  
dest=/etc/example.conf  
section=test  
option=example  
value=value

Just add one option/value pair for each required option. Unfortunately, in my case, the config file in question isn’t actually an ini-style file, so ini\_file doesn’t work.

---

<div class="post-metadata">

**Author:** ![Walid](https://avatars.discourse-cdn.com/v4/letter/w/ea5d25/32.png) [@Walid](https://forum.ansible.com/u/Walid)\
**Post date:** [February 10, 2014, 5:06pm UTC](https://forum.ansible.com/t/lineinfile-task-that-spans-multiple-lines/14512/5 "2014-02-10T17:06:56Z")

</div>

sed/grep will not affect your file, they will just get how many lines you would like to change

---

<div class="post-metadata">

**Author:** ![Chris\_McConnell](https://avatars.discourse-cdn.com/v4/letter/c/90db22/32.png) [@Chris\_McConnell](https://forum.ansible.com/u/Chris_McConnell)\
**Post date:** [February 26, 2016, 1:03am UTC](https://forum.ansible.com/t/lineinfile-task-that-spans-multiple-lines/14512/6 "2016-02-26T01:03:56Z")

</div>

Hello, although this is an older thread, I came across it today while searching for a solution to also use lineinfile to edit multiple lines after a designated regex.  
Apologies if this is not the right way to do it, (and if its a bad way, would love to see the “right” way to do it). But hey, I just needed to get it done and this one was a bit of a challenge.

Note the syntax to get around the YAML gotcha with the command below. Here’s is what worked for me although disclaimer YMMV.

# idempotent using with multiline regex with register

- name: “Test for subjectAltName = IP in /etc/pki/tls/openssl.cnf”  
command: ‘grep “^subjectAltName = IP: {{ (ansible\_eth0 | default(ansible\_lo)).ipv4.address }}” /etc/pki/tls/openssl.cnf’  
register: test\_grep  
failed\_when: “‘PLACEHOLDERHACK’ in test\_grep.stderr”  
#ignore\_errors: yes

- name: “modify SSL cert configuration add subjectAltName = IP to /etc/pki/tls/openssl.cnf”  
lineinfile: ‘dest=/etc/pki/tls/openssl.cnf regexp=“^[v3\_ca]” state=present insertafter=“^[v3\_ca]” line=“[v3\_ca]\nsubjectAltName = IP: {{ (ansible\_eth0 | default(ansible\_lo)).ipv4.address }}” backup=yes’  
when: test\_grep.stdout == “”

Idempotent result in edited file Where the nodes IP is ‘192.168.xx.xx’:

Original target file was just the section:  
[v3\_ca]

Idempotent result (post multiple iterations) in edited target file then included section and the desired IP:

[v3\_ca]  
subjectAltName = IP: 192.168.xx.xx

Note that I actually had to modify the above code for our handling of virtual hosts running CentOS-7 as I was getting “ansible\_eth0.ipv4.address is undefined” errors.  
Were still running ansible 1.9.4, but I also tried upgrading to latest ansible version (as of 2016-02-35) version 2.x and still saw the problem.  
Let me know if seeing the other workaround for handling dynamically named (and specific) network interfaces on CentOS-7 might be useful.
