Background
I needed to find a way to add new paths to a quoted line in the following file:
File: /etc/updatedb.com
Line: PRUNEPATHS = “/afs /media /net /sfs /tmp /udev /var/cache/ccache /var/spool/cups /var/spool/squid /var/tmp”
Should be simple. This is something I can do with awk/sed all day long. Well it turned out to not be that simple in Ansible, if I wanted to do it using the existing modules. So here is what I did, and it worked great. Of course if anyone knows how to simplify this I am all ears:
Play
(Explanation to follow)
- name: Configure updatedb to ignore the /db path
lineinfile:
dest=/etc/updatedb.conf
backrefs=True
state=present
regexp=‘(^PRUNEPATHS\s+=\s+)(?:“)([\w+\s/]+)(?<!/db)(?:”)’
line=‘\1"\2 /db"’
Explanation:
I wanted a regex that would match the entire line if /db was not in it, and then create 2 capture groups from the data. Because I wanted to insert /db if it was missing, within the quoted section, I felt it was better to construct the line from parts removing the " characters. As you see from the line=, I add them back in.
Breakdown of Regex
(^PRUNEPATHS\s+=\s+) # I wanted to match "PRUNEPATHS = " and capture in capture group 1
(?:") # I wanted to search on the string with the " so it would match but did not want to capture the ". (?:…) does this.
([\w+\s/]+) # I wanted to match on any of the characters and formats this line would be in and assign this to capture group 2. Here I match on one or more alpha, spaces and / and any number of the previous combos, again only in the line starting with the first part of the regex. This effectively will match anything in format “/afs /media /net /sfs /tmp /udev /var/cache/ccache /var/spool/cups /var/spool/squid /var/tmp” that also meets the first element of the regex
(?<!/db) # This is a negative look behind assertion. I wanted to not match if the line contained /db anywhere as there is no need to add it if the line has it already. I did this here because at this stage the regex has the entire line minus the " in buffer, so makes sense to do the NLBA.
(?:") # Match on the final quote but don’t capture it.
What this gives me
A match result of the following completely constructed and ordered based on whats in the file: PRUNEPATHS = “/afs /media /net /sfs /tmp /udev /var/cache/ccache /var/spool/cups /var/spool/squid /var/tmp”
2 capture groups (1,2) and here is what they contain (minus the quotes):
1: "PRUNEPATHS = "
2: “/afs /media /net /sfs /tmp /udev /var/cache/ccache /var/spool/cups /var/spool/squid /var/tmp”
From there I construct the line that lineinfile will create
\1 # capture group 1 contents
" # escaped quote
\2 # capture group 2 contents
/db # Actual text I am appending
" # escaped quote
The line is changed from:
PRUNEPATHS = “/afs /media /net /sfs /tmp /udev /var/cache/ccache /var/spool/cups /var/spool/squid /var/tmp”
to:
PRUNEPATHS = “/afs /media /net /sfs /tmp /udev /var/cache/ccache /var/spool/cups /var/spool/squid /var/tmp /db”
Hopefully someone finds this useful.
Bill Clark