27

I'm parsing a file with key=value data and then export them as environment variables. My solution works, but not with special characters, example:

.data

VAR1=abc
VAR2=d#r3_P{os-!kblg1$we3d4xhshq7=mf$@6@3l^

script.sh

#!/bin/bash
while IFS="=" read -r key value; do
  case "$key" in
    '#'*) ;;
    *)
      eval "$key=\"$value\""
      export $key
  esac
done < .data

$ . ./script.sh

Output:

$ echo $VAR1
abc
$ echo $VAR2
d#r3_P{os-!kblg1=mf6@3l^

but should be: d#r3_P{os-!kblg1$we3d4xhshq7=mf$@6@3l^

User
  • 1,978
  • 5
  • 26
  • 47

5 Answers5

47

Just use single quotes:

export VAR2='d#r3_P{os-!kblg1$we3d4xhshq7=mf$@6@3l^'
Bernardo Ramos
  • 4,048
  • 30
  • 28
17

Just escape the $ sign with backslash \

Yedidia
  • 969
  • 7
  • 12
  • 3
    If the data is automatically generated by some 3rd-party application and saved in the `.data` file then you might not be able to do it in an automated environment – Rogus Apr 19 '17 at 12:37
  • 1
    how do you escape `&` ? – nurettin May 05 '19 at 10:54
  • 1
    also with a backslash, here is an exmaple: `# echo \&` `&` – Yedidia May 06 '19 at 12:38
  • 1
    Very inefficient if you have multiple characters that will need to be passed escaped – Mitch Aug 31 '19 at 18:15
  • you escape ^ in the same manner. I do not have the list of special characters that can be escaped with \ but one can empirically conjecture and verify at the command line – David Nov 02 '21 at 19:01
3

You don't need eval at all, just use declare built-in in bash to create variables on-the-fly!

case "$key" in
  '#'*) ;;
   *)
       declare $key=$value
       export "$key"
esac
Inian
  • 80,270
  • 14
  • 142
  • 161
3

I found the following script (to be sourced) helpful:

set -a
source <(cat development.env | \
    sed -e '/^#/d;/^\s*$/d' -e "s/'/'\\\''/g" -e "s/=\(.*\)/='\1'/g")
set +a

From: https://stackoverflow.com/a/66118031/339144

Klaas van Schelven
  • 2,374
  • 1
  • 21
  • 35
2

If you cannot change the .data file you have to escape the special character $ when assigning the value to key. Change the assignment line to:

eval "$key=\"${value//\$/\\\$}\""

${variable//A/B} means substituting every instance of A to B in variable.

More useful info on bash variables here

Rogus
  • 750
  • 5
  • 11