0

Given:

~$ cat .test-profile
export ADMIN_EMAIL=info@mail.com
export MONGODB_URI='mongodb+srv://administrator:abcdef@mysite-cluster-n1qub.mongodb.net/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:abcdef@mysite-cluster-n1qub.mongodb.net/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' 'bob@gmail.com'
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 ADMIN_EMAIL=bob@gmail.com
export MONGODB_URI='mongodb+srv://administrator:abcdef@mysite-cluster-n1qub.mongodb.net/mysite_development?retryWrites=true&w=majority'

Notice 'mysite_development' replaces 'test'.

  • 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). – Paulo Tomé Feb 16 at 0:40
  • @PauloTomé adding ' seems to produce a result but not completely replacing old value with new value. – Donato Feb 16 at 0:55
  • You have unescaped & in the replacement string. – NickD Feb 16 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 at 2:16
  • I have - did you escape your ampersands? – NickD Feb 16 at 2:32
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:abcdef@mysite-cluster-n1qub.mongodb.net/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' 'bob@gmail.com'
INSERT_ENV_VAR 'MONGODB_URI' $MONGODB_URI

and running this with the test profile, I get:

export ADMIN_EMAIL=bob@gmail.com
export MONGODB_URI=mongodb+srv://administrator:abcdef@mysite-cluster-n1qub.mongodb.net/mysite_development?retryWrites=true&w=majority
| improve this answer | |
  • Yes, I deleted the comment earlier because it did work. – Donato Feb 16 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 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
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.