Code Explainer: Regex and Backrefs in Ansible Code
Tags: ansible, lineinfile, regex
Published: 2022-10-06 14:30:39

---
title: Code Explainer: Regex and Backrefs in Ansible Code
published: true
date: 2022-09-23 18:43:00 UTC
tags: Ansible,lineinfile,regex
canonical_url: https://thjones2.blogspot.com/2022/09/code-explainer-regex-and-backrefs-in.html
---

Recently, I'd submitted a code-update to a customer-project I was working on. I tend to write very dense code, even when using simplification frameworks like Ansible. As a result, I had to answer some questions asked by the person who did the code review. Ultimately, I figured it was worth writing up an explainer of what I'd asked them to review…

The Ansible-based code in question was actually just _one_ play:

```
---
- name: Remove sha512 from the LOG option-list
  ansible.builtin.lineinfile:
    backrefs: true
    line: '\g<log>\g<equals>\g<starttoks>\g<endtoks>'
    path: /etc/aide.conf
    regexp: '^#?(?P<log>LOG)(?P<equals>(\s?)(=)(\s?))(?P<starttoks>.*\w)(?P<rmtok>\+?sha512)(?P<endtoks>\+?.*)'
    state:present
...
```

The above is meant to ensure that the contents of the RHEL 7 config file, "<tt>/etc/aide.conf</tt>" sets the propper options on for the defined scan-definition, "LOG". The original contents of the line were:

```
LOG = p+u+g+n+acl+selinux+ftype+sha512+xattrsfor
```

The STIGs were updated to indicate that the contents of that line should actually be:

```
LOG = p+u+g+n+acl+selinux+ftype+xattrsfor
```

The values of the Ansible play's <tt>regexp</tt> and <tt>backrefs</tt> attributes are designed to use the advanced line-editing afforded through the [Ansible <tt>lineinfile</tt> module's](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/lineinfile_module.html) capability. Ansible is a Python-based service. This module's advanced line-editing capabilities are implemented using Python's [<tt>re()</tt> function](https://docs.python.org/3/library/re.html). The <tt>regexp</tt> attribute's value is written to make use of the <tt>re()</tt> function's ability to do referenceable search-groupings. Search-groupings are specified using parenthesis-delimited search-rules (i.e., "<tt>(SEARCH_SYNTAX)</tt>").

By default, a given search-grouping is referenced by a left-to-right index-number. These number starting at "<tt>1</tt>". The reference-IDs can then be referenced – also refered to as "backrefs" – in the replacement-string (through the value of the play's <tt>line</tt> attribute) to help construct the replacement string's value. Using the index-number method, the replacement-string would be "<tt>\1\2\6\8"</tt> …which isn't exactly self-explanatory.

To help with readability, each group can be explicitly-named. To assign a name to a search-group, one uses the syntax <tt>?P&lt;LABEL_NAME&gt;</tt> at the beginning of the search-group. Once the group is assigned a name, it can subsequently be referenced by that name using the syntax "<tt>\g&lt;LABEL_NAME&gt;</tt>".

If one visits the [Regex101](https://dev.to/scottw/-regex-101-ei9-temp-slug-1258619) web-site and selects the "Python" regex-type from the left menu, one can get a visual representation of how the above <tt>regexp</tt> gets interpreted. Enter the string to be evaluated in the "<tt>TEST STRING</tt>" section and then enter the value of the <tt>regexp</tt> parameter in the <tt>REGULAR EXPRESSION</tt> box. The site will then show you how the regex chops up the test string and tell you why it chopped it up that way:

![Regex101 Screen-cap](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRPrPUtCDftaVz2-_MvC5uFnP63LUX710XSRffuucoK-OT5jIO0rFTtWUrw4Mmei0sKX2fiecY8lJ5k1Uos8aHJwUA4m3Od29Z4hd2SA05sMxSrbqEczDgx9a5t9FTSNk2jKhfxAr8ghzjNUkLNGtFen6GTYL--nh1puCJsn7_cOt-euBUSrGL9-1L/w790-h479/Regex101.png)