0

Given:

~$ cat .test-profile
export [email protected]
export MONGODB_URI='mongodb+srv://administrator:[email protected]/test?retryWrites=true&w=majority'

I wrote the following shell script to replace the variable values:

BASH_PROFILE="$HOME/.test-profile"
MONGODB_URI="mongodb+srv://administrator:[email protected]/mysite_development?retryWrites=true&w=majority"

INSERT_ENV_VAR () {
  if [[ -z "$2" ]]
    then
      echo "Failed to retrieve $1"
   else
    if grep -q "$1" "$BASH_PROFILE"; then
      # Cannot use / delimiter, for value can contain /
      sed -in -E "s|(export $1=)[a-zA-Z0-9@.:\/=&\-\?\+]+|\1$2|g" "$BASH_PROFILE"
    else
      echo "export $1=$2" >> "$BASH_PROFILE"
    fi
  fi
}

INSERT_ENV_VAR 'ADMIN_EMAIL' '[email protected]'
INSERT_ENV_VAR 'MONGODB_URI' $MONGODB_URI

While the ADMIN_EMAIL variable is replaced fine, the MONGODB_URI variable is not being replaced. And I believe it has to do something with the character class [] inside of the regex. But I am not sure what. I tried it in a programming language like ruby and it found the match. But with sed it isn't finding the match. Why?

This is what I expect .test-profile to look like afterwards:

export [email protected]
export MONGODB_URI='mongodb+srv://administrator:[email protected]/mysite_development?retryWrites=true&w=majority'

Notice 'mysite_development' replaces 'test'.

6
  • The problem seems to be related with the ' character. Try your sed with (export MONGODB_URI=)[a-zA-Z0-9@.:\/=&\-\?\+']+ (adds a ' to the list of valid characters). Feb 16, 2020 at 0:40
  • @PauloTomé adding ' seems to produce a result but not completely replacing old value with new value. Feb 16, 2020 at 0:55
  • You have unescaped & in the replacement string.
    – NickD
    Feb 16, 2020 at 2:14
  • Also why use such a complicated regex? Why not "s|(export $1=).*|\1$2|"? And why use g? But you still have to escape & in $2.
    – NickD
    Feb 16, 2020 at 2:16
  • I have - did you escape your ampersands?
    – NickD
    Feb 16, 2020 at 2:32

2 Answers 2

0

Escaping the ampersand in the definition of MONGODB_URI in the script and simplifying the regex, getting rid of the -n and getting rid of the unnecessary g in the sed, we end up with this (the test profile is named differently in this version, but it should be clear what to do):

BASH_PROFILE="/tmp/test_profile"
MONGODB_URI="mongodb+srv://administrator:[email protected]/mysite_development?retryWrites=true\&w=majority"

INSERT_ENV_VAR () {
  if [[ -z "$2" ]]
    then
      echo "Failed to retrieve $1"
   else
    if grep -q "$1" "$BASH_PROFILE"; then
      # Cannot use / delimiter, for value can contain /
      sed -i -E "s;(export $1=).*;\1$2;" "$BASH_PROFILE"
    else
      echo "export $1=$2" >> "$BASH_PROFILE"
    fi
  fi
}

INSERT_ENV_VAR 'ADMIN_EMAIL' '[email protected]'
INSERT_ENV_VAR 'MONGODB_URI' $MONGODB_URI

and running this with the test profile, I get:

export [email protected]
export MONGODB_URI=mongodb+srv://administrator:[email protected]/mysite_development?retryWrites=true&w=majority
2
  • Yes, I deleted the comment earlier because it did work. Feb 16, 2020 at 2:44
  • This will result in some inconsistency – when grep succeeds and sed is used the replacement made by sed won't contain a backslash before the &, but if the append-echo is used the `\` remains
    – user391836
    Feb 17, 2020 at 12:58
0
sed -i "/export $1=/{i export $1='$2'
    ;d}" "$BASH_PROFILE"

This will allow you to use sed without needing to replace & with \&

  • grep -q could have the options -F and also -m 1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .