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.

Meme showing a tired runner representing me still processing 2020 when a fresh runner representing 2022 arrives very quickly at my back

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…