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