Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Parse a .env (dotenv) file directly using BASH
# Pass the env-vars to MYCOMMAND
eval $(egrep -v '^#' .env | xargs) MYCOMMAND
# … or ...
# Export the vars in .env into your shell:
export $(egrep -v '^#' .env | xargs)
@kowalk

This comment has been minimized.

Copy link

kowalk commented Feb 16, 2018

If you want just set a single variable in your script just use code below:
MY_VAR=$(grep MY_VAR .env | xargs)
IFS='=' read -ra MY_VAR <<< "$MY_VAR"
MY_VAR=${MY_VAR[1]}

@rafaelbeckel

This comment has been minimized.

Copy link

rafaelbeckel commented Mar 17, 2018

read_var() {
    VAR=$(grep $1 $2 | xargs)
    IFS="=" read -ra VAR <<< "$VAR"
    echo ${VAR[1]}
}

MY_VAR=$(read_var MY_VAR .env)
@desprit

This comment has been minimized.

Copy link

desprit commented Mar 26, 2018

MY_VAR=$(grep MY_VAR .env | xargs)
MY_VAR=${MY_VAR#*=}

dunno about possible drawbacks though

@pronebird

This comment has been minimized.

Copy link

pronebird commented May 27, 2018

It won't work if you have spaces, i.e FOO="BAR BUZ" will be returned without quotes from xargs

@revolter

This comment has been minimized.

Copy link

revolter commented May 30, 2018

Use xargs -d '\n' on GNU systems or xargs -0 on BSD systems to handle values with spaces.

https://stackoverflow.com/a/32589977/865175

@amberdiehl

This comment has been minimized.

Copy link

amberdiehl commented Aug 10, 2018

I have nothing technical to add; just saying thank you. This is exactly what I needed.

@dovidweisz

This comment has been minimized.

Copy link

dovidweisz commented Aug 30, 2018

Here's a one-liner for getting one variable:

MY_VAR=$(grep MY_VAR .env | cut -d '=' -f2)

One issue i see with all these solutions is: what happens if i have two similar variables. I need to fix the Grep part to only match ^MY_VAR=. I'm just not that good with grep.

Also... i would never have thought about using grep here, so Thank You.

@damcclean

This comment has been minimized.

Copy link

damcclean commented Nov 10, 2018

Perfect! Exactly what I was looking for :)

@twalling

This comment has been minimized.

Copy link

twalling commented Dec 14, 2018

I had to change the one-liner by @dovidweisz so that all of my var was included. If you have equal signs in your var which we're also using as the delimiter then you have to tell cut to include all the rest of the fields

MY_VAR=$(grep MY_VAR .env | cut -d '=' -f 2-)
@msmans

This comment has been minimized.

Copy link

msmans commented Dec 20, 2018

With GNU grep, you can simply do MY_VAR=$(grep -oP '^MY_VAR=\K.*' .env)

@Jules-Baratoux

This comment has been minimized.

Copy link

Jules-Baratoux commented Dec 26, 2018

I use the following to avoid overriding already set variable:

source <(grep -v '^#' .env | sed -E 's|^(.+)=(.*)$|: ${\1=\2}; export \1|g')
@heycarsten

This comment has been minimized.

Copy link

heycarsten commented Jan 2, 2019

I’ve been doing it like this:

# Load up .env
set -o allexport
[[ -f .env ]] && source .env
set +o allexport

It seems to work great… are their drawbacks to this?

In my case I’m just loading in the variables to use for in-project commands (in bin)

✌️

@darrenleeweber

This comment has been minimized.

Copy link

darrenleeweber commented Feb 10, 2019

When this is in a script, allow an existing ENV variable or CLI to override the .env file and only try to use a .env file if it exists:

test -z "$VAR" && test -f .env && \
    VAR=$(grep -e '^VAR=.*' .env | cut -d '=' -f2)

Add an export VAR if necessary.

@seeekr

This comment has been minimized.

Copy link

seeekr commented Mar 5, 2019

If you're having trouble with spaces still messing up your loading of the variables, use this:

IFS='
'
export $(egrep -v '^#' .env | xargs -0)
IFS=

(Replace xargs -0 with xargs -d '\n' if you're not on macOS.)

Explanation: IFS changes what bash splits strings on. By default it splits on spaces, but using the above it only does so on newlines. We reset its behavior after we're done.

@TechupBusiness

This comment has been minimized.

Copy link

TechupBusiness commented Apr 7, 2019

This works fine (as long as you don't use "=" in your values):

read_var() {
    VAR=$(grep "^$1=" $2 | xargs)
    IFS="=" read -ra VAR <<< "$VAR"
    IFS=" "
    echo ${VAR[1]}
}
@miguelmota

This comment has been minimized.

Copy link

miguelmota commented Jun 24, 2019

Here's a version to make the filename optional and use .env as default:

read_var() {
  if [ -z "$1" ]; then
    echo "environment variable name is required"
    return
  fi

  local ENV_FILE='.env'
  if [ ! -z "$2" ]; then
    ENV_FILE="$2"
  fi

  local VAR=$(grep $1 "$ENV_FILE" | xargs)
  IFS="=" read -ra VAR <<< "$VAR"
  echo ${VAR[1]}
}

Example usage:

local my_var=$(read_var MY_VAR)
local my_other_var=$(read_var MY_VAR staging.env)
@AdamGerthel

This comment has been minimized.

Copy link

AdamGerthel commented Jul 10, 2019

God I wish it was possible to upvote the different solutions here. I have no idea which one to pick.

@judy2k

This comment has been minimized.

Copy link
Owner Author

judy2k commented Jul 10, 2019

@AdamGerthel bear in mind that there are actually two different problems being solved in these solutions. The original is parsing a whole .env file - many of the other 'solutions' are extracting a single value from a .env file.

(This was never intended to be a popular/controversial gist - I was just putting it here for my own use!)

@AdamGerthel

This comment has been minimized.

Copy link

AdamGerthel commented Jul 10, 2019

@judy2k right - and I eventually found this on SO: https://stackoverflow.com/a/20909045/930998

@cdcabrera

This comment has been minimized.

Copy link

cdcabrera commented Jul 12, 2019

Awesome @miguelmota much appreciated! I updated it a little

read_var() {
  local ENV_FILE="${2:-./.env}"
  local VAR=$(grep $1 "$ENV_FILE" | xargs)

  IFS="=" read -ra VAR <<< "$VAR"
  echo ${VAR[1]}
}
@Norcoen

This comment has been minimized.

Copy link

Norcoen commented Aug 8, 2019

I’ve been doing it like this:

# Load up .env
set -o allexport
[[ -f .env ]] && source .env
set +o allexport

It seems to work great… are their drawbacks to this?

In my case I’m just loading in the variables to use for in-project commands (in bin)

v

Personally I use

set -a
[ -f .env ] && . .env
set +a

it does the same, but it should be POSIX compatible

@peteratticusberg

This comment has been minimized.

Copy link

peteratticusberg commented Oct 26, 2019

export $(cat .env) works for basic use cases

@cocowalla

This comment has been minimized.

Copy link

cocowalla commented Nov 15, 2019

export $(cat .env) works for basic use cases

What kind of cases does it not work for

EDIT: Answering my own question: it doesn't work for quoted strings

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.