Devops 101: How to deal with regexes in Ansible's YAML
My last post on this blog was almost a year ago. Yes, I haven’t been very talkative this year, even though I said in the previous post that I was starting a new series. I’m sorry. It’s been a very… weird year.

So, to make it up to you, today, I’ll give you a little tip on how to correctly handle regexes
in YAML. This may prove particularly useful with Ansible’s lineinfile module.
The situation
Using Ansible, you may quickly find yourself in a situation where you need to modify a
configuration file. Like every sensible Ansible user, you will use Ansible’s
lineinfile.
It turns out that some of the lines you try to replace contain characters that have
a special meaning in Python’s regex language. Like [ or .. So you’ll need to escape them.
And you’ll bang your head on the wall because YAML has a special way of handling escaping.
The solution
YAML has 2 types of strings. Double-quoted strings: "this is a YAML string" and
single-quoted strings: 'this is also a string in YAML'. But they’re not strictly equivalent.
In double-quoted strings, escape sequences using \ are interpreted by the YAML parser and
only certain characters can be escaped. Namely: \\, \" to produce litteral double-quotes and
litteral backspaces, \b, \f, \n, \r and \t to produce various blank characters and \u
to produce unicode characters. Any other escaped characters will produce an error.
In single-quoted characters, on the other hand, escape sequences using \ don’t mean anything
special to YAML. So you can use \[ to escape regex special characters.
The single-quote character exception
So far, there’s nothing particularly tricky in what I just explained. It’s certainly easy to
miss, but if you carefully ready lineinfile’s documentation, all example use single-quoted
strings so you may be fine.
But you may wonder: “hey, what if the line I’m trying to replace contains a litteral single-quote?”. Something like:
nginx['listen_addresses']
in Gitlab’s configuration.
You may try to escape them but remember: escape sequence aren’t interpreted in YAML’s single-quoted string so this will still result in an error.
The correct way to insert a litteral single-quote in YAML’s single-quoted strings is to double it:
lineinfile:
regexp: 'nginx\[''listen_addresses''\]'
And that’s it!
This was a relatively short article, compared to what I usually write, but many of my Ansible students stumble over this tricky situation. So I thought it might be useful to others…