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 theregex_replacewith'PREFIX_\\1: \\2', but you’ll note that it prefixes everything withinKEY1because 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