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
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
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
.. 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.
YAML has 2 types of strings. Double-quoted strings:
"this is a YAML string" and
'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
\t to produce various blank characters and
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:
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…