1

I have .env file and I am trying to parse the value from it.

I ran this

cat .env | grep PORT=

I got

PORT=3333

How do I grab the value of a specific key?

Barmar
  • 741,623
  • 53
  • 500
  • 612
code-8
  • 54,650
  • 106
  • 352
  • 604
  • Use 'cut' command – nachiketkulk Apr 30 '18 at 19:57
  • 1
    Assign the output to a variable, and then use a [Parameter Expansion operator](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html#Shell-Parameter-Expansion) to get the part after `=`. – Barmar Apr 30 '18 at 19:58
  • I don't want to change anything, I just want to read from it. – code-8 Apr 30 '18 at 19:59
  • 1
    I never said anything about changing anything. – Barmar Apr 30 '18 at 20:00
  • 3
    `line=$(grep PORT= .env)` and then get the part of `$line` after `=`. – Barmar Apr 30 '18 at 20:00
  • 1
    Possible duplicate of [grep for contents AFTER pattern](https://stackoverflow.com/q/10358547/608639), [Get string after character](https://stackoverflow.com/q/15148796/608639), [cut for key-value pairs](https://unix.stackexchange.com/q/186453/56041), [Extract values from key-value pair and output values](https://unix.stackexchange.com/q/321883/56041), etc. – jww May 01 '18 at 00:23

3 Answers3

6
cat env | grep PORT= | cut -d '=' -f2
nachiketkulk
  • 1,141
  • 11
  • 22
  • 2
  • You are right! There are several ways to do this. I presented one of those. – nachiketkulk Apr 30 '18 at 20:04
  • 3
    Sure -- but if you're going to present one way, why not try to optimize for a best-practice approach? The extra `cat` doesn't matter much in this specific case, but it's a bad habit to get people in -- `cat foo | wc -c` stops `wc` from being able to just use `seek()` and `tell()` to get the size of its input file in constant time, f/e, so the impact can be much larger in other commands. (Similarly, GNU `sort` can parallelize on large input files... but only when reading from a seekable file, not from a FIFO, which can only be read a single time, front-to-back). – Charles Duffy Apr 30 '18 at 20:05
  • 1
    I was looking for something like this to parse `/etc/os-release` for `ID`, and this returned the value of `VERSION_ID`. grepping for `^ID` fixed that for me. – Augustine Calvino Jan 29 '22 at 20:18
3

Let say your input looks like this :

$ cat test.txt
Port=2020
Email=me@myserver.com
Version=2.02

Then this will do :

awk -F'=' '/^Version/ { print $2}'  test.txt

Output

2.02
Matias Barrios
  • 4,674
  • 3
  • 22
  • 49
0

Use eval to parse the assignment line, later variable values can be substituted with $:

eval "$(grep ^PORT= .env)"
echo $PORT
FBergo
  • 1,010
  • 8
  • 11
  • 1
    This is going to change the environment of the whole script, possibly including things like `PATH`. – Barmar Apr 30 '18 at 19:59
  • I don't want to change anything, I just want to read from it. – code-8 Apr 30 '18 at 19:59
  • `grep ^PORT= .env > tmp.sh`, `source tmp.sh` – FBergo Apr 30 '18 at 20:03
  • 1
    At that point you could `eval "$(grep ^PORT= .env)"` and avoid the temporary file. That way, also, you avoid the vulnerability to a symlink attack from using a hardcoded tempfile name. (Still vulnerable to a `PORT=$(rm -rf ~)` config file, of course). – Charles Duffy Apr 30 '18 at 20:03
  • I've edited the answer to use eval on the single grep'ed line with the desired variable. – FBergo Apr 30 '18 at 20:08
  • 1
    `eval $foo` is less reliable than `eval "$foo"` (as it isn't a syntactic element that suppresses string-splitting, its arguments get string-split, glob-expanded, and then joined back together into a string) -- and backticks for command substitution are considered legacy syntax (hard to nest, and backslashes have a different meaning within them than outside). Please consider the syntax I suggested in the comment above. – Charles Duffy Apr 30 '18 at 20:12
  • Run `foo=$'printf \'%s\n\' "hello world" "goodbye world"'`, and then compare `eval $foo` and `eval "$foo"` for an example. And that's a relatively tame one; it's easy to expand local filenames into your code if the content being evaluated has a wildcard with whitespace on both ends, f/e. – Charles Duffy Apr 30 '18 at 20:14