Environment variable substitution in sed

Viewed 345882

If I run these commands from a script:

#my.sh
PWD=bla
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
xxx
bla

it is fine.

But, if I run:

#my.sh
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
$ sed: -e expression #1, char 8: Unknown option to `s' 

I read in tutorials that to substitute environment variables from shell you need to stop, and 'out quote' the $varname part so that it is not substituted directly, which is what I did, and which works only if the variable is defined immediately before.

How can I get sed to recognize a $var as an environment variable as it is defined in the shell?

12 Answers

Your two examples look identical, which makes problems hard to diagnose. Potential problems:

  1. You may need double quotes, as in sed 's/xxx/'"$PWD"'/'

  2. $PWD may contain a slash, in which case you need to find a character not contained in $PWD to use as a delimiter.

To nail both issues at once, perhaps

sed 's@xxx@'"$PWD"'@'

In addition to Norman Ramsey's answer, I'd like to add that you can double-quote the entire string (which may make the statement more readable and less error prone).

So if you want to search for 'foo' and replace it with the content of $BAR, you can enclose the sed command in double-quotes.

sed 's/foo/$BAR/g'
sed "s/foo/$BAR/g"

In the first, $BAR will not expand correctly while in the second $BAR will expand correctly.

You can use other characters besides "/" in substitution:

sed "s#$1#$2#g" -i FILE

With your question edit, I see your problem. Let's say the current directory is /home/yourname ... in this case, your command below:

sed 's/xxx/'$PWD'/'

will be expanded to

sed `s/xxx//home/yourname//

which is not valid. You need to put a \ character in front of each / in your $PWD if you want to do this.

If your replacement string may contain other sed control characters, then a two-step substitution (first escaping the replacement string) may be what you want:

PWD='/a\1&b$_' # these are problematic for sed
PWD_ESC=$(printf '%s\n' "$PWD" | sed -e 's/[\/&]/\\&/g')
echo 'xxx' | sed "s/xxx/$PWD_ESC/" # now this works as expected

for me to replace some text against the value of an environment variable in a file with sed works only with quota as the following:

sed -i 's/original_value/'"$MY_ENVIRNONMENT_VARIABLE"'/g' myfile.txt

BUT when the value of MY_ENVIRONMENT_VARIABLE contains a URL (ie https://andreas.gr) then the above was not working. THEN use different delimiter:

sed -i "s|original_value|$MY_ENVIRNONMENT_VARIABLE|g" myfile.txt
Related