Ansible regex to parse multi-line .env file

Advertisements

Please note: there are always alternatives to this, but this is more of an interest / challenge – please focus on the question itself, specifically how to parse a .env file with a valid regex in Ansible. I’m very close.

I have a .env file that I’d like to parse into ansible variables within an ansible playbook. I currently have this working with simple key=value pairs, and also ignoring comments and new lines.

This is the regex replace that works:

map('regex_replace', '([^=]*)=(.*)', '\\1: \\2')

And the .env file it parses.

KEY2=SOME_TEXT
KEY3="SOME_MORE_TEXT"
KEY4='EVEN_MORE_TEXT'

Problem

However, when I have a multi-line variable in this file, such as:

KEY1='{
    "string" = {
        "key" = "value",
        "key" = "value"
    },
    "string" = {
        "key" = "value",
        "key" = "value"
    }
}'

… then the regex still parses it, but it also changes all of the = into : within that string. I want to ignore anything within those single quotes, and I don’t know how to do that.

Here is the full playbook with the regex I have so far:

---
- name: Read .env file
  hosts: "localhost"
  connection: "local"
  tasks:
    - name: Get env file content
      slurp:
        src: ../.env
      register: env_file_content

    - name: Store env vars in playbook values
      set_fact:
        env_vars: "{{ (env_file_content.content | b64decode).split('\n') | map('regex_replace', '^#.*', '') | select | map('regex_replace', '([^=]*)=(.*)', '\\1: \\2') | join('\n') | from_yaml }}"

    - name: Debug output
      debug:
        var: env_vars

and the full .env file:

# IN TOTAL, THE REGEX SHOULD MATCH 4 KEY-VALUE PAIRS FROM THIS FILE.
KEY1='{
    "string" = {
        "key" = "value",
        "key" = "value"
    },
    "string" = {
        "key" = "value",
        "key" = "value"
    }
}'

# DO NOT MATCH ON COMMENTS, EVEN THOSE WITH X=Y in them.

# ALSO IGNORE THIS COMMENT, AND NEW LINES AROUND.

KEY2=SOME_TEXT
KEY3="SOME_MORE_TEXT"
KEY4='EVEN_MORE_TEXT'

What I need

  • The regex needs to yield four variables that can be accessed in Ansible such as env_vars.KEY1.
  • The regex needs to NOT match anything within KEY1 – it needs to be left untouched.
  • It also needs to prefix each key with PREFIX_, which can be done in the regex_replace with 'PREFIX_\\1: \\2', but you’ll note that it prefixes everything within KEY1 because it matches on the contents of that variable, when I want to ignore that.

How can I update what I have so far to parse a multi-line .env file with a Regex (and prefix each var with a string) in ansible so that I can access the four individual variables?

>Solution :

If you want to use a regex, you might use:

^([^"\s=]+)=('{[\s\S]*?\n}'|.*)

In the replacement you can use PREFIX_\\1: \\2

The pattern matches:

  • ^ Start of string
  • ([^"\s=]+) Capture group 1, match 1+ non whitespace chars other than " and =
  • = Match literally
  • ( Capture group 2
    • '{ Match '{
    • [\s\S]*? Match any character including newlines, as few as possible
    • \n}' Match a newline and then }'
    • | Or
    • .* Match the whole line without newlines
  • ) Close group 2

See a regex demo

Leave a ReplyCancel reply