简体   繁体   中英

Sed string replace using environment variable

I have a situation where variables are set in the environment and I have to replace those variable in the file with its value.

Example, I have a lot variable set few of them are FRUIT=APPLE, TIME=DAILY. The content of the text file is

The $$FRUIT$$ is good for health. Everyone should eat $$FRUIT$$ $$TIMES$$.

Now I want a sed command to search any string in $$$$ and use it as env variable to get the value and replace it in the file.

The APPLE is good for health. Everyone should eat APPLE DAILY.

I tried

sed -i -E "s|$$([A-Z]+)$$|${\1}|g" test.txt

and multiple other combination, but its not working.

it gives me error -bash: s|$$([AZ]+)$$|${\1}|g: bad substitution

This steals from my answer to How can I interpret variables on the fly in the shell script? -- this question isn't quite a duplicate of that one.

str='The $$FRUIT$$ is good for health. Everyone should eat $$FRUIT$$ $$TIMES$$'
FRUIT=APPLE
TIMES=DAILY

while [[ $str =~ ('$$'([[:alnum:]_]+)'$$') ]]; do
    str=${str//${BASH_REMATCH[1]}/${!BASH_REMATCH[2]}}
done

echo "$str"
The APPLE is good for health. Everyone should eat APPLE DAILY

We search for the template string, capturing the whole string with the dollar signs, and also capture just the variable name within. Then we use shell parameter expansion to replace the matched template string with the value of the variable, using indirect variable expansion .

This steals from the answer to How can I interpret variables on the fly in the shell script? -- this question isn't quite a duplicate of that one.

Provided that the variables are part of the environment:

export FRUIT="APPLE"
export TIMES="DAILY"

You can use the envsubst GNU tool to perform the variable replacement:

echo 'The $$FRUIT$$ is good for health. Everyone should eat $$FRUIT$$ $$TIMES$$.' | sed -E 's/\$\$([A-Z]+)\$\$/${\1}/g' | envsubst
The APPLE is good for health. Everyone should eat APPLE DAILY.

Note that you need to put a backslash before the $ character since this character has a meaning for sed.

Here's how to do it with only sed and grep

list=$(grep -wo "\\$\S\S*\\$" test2 | sort -u | tr '$' '\n');
for thing in ${list[@]}; do sed -i 's/\$\$'$thing'\$\$/'$"${!thing}"'/g' test2; done

Below is some explanation (self evident)

user$ echo $TIMES
DAILY
user$ echo $FRUIT
APPLE
user$ cat test2 
The $$FRUIT$$ is good for health. Everyone should eat $$FRUIT$$ $$TIMES$$.
user$ list=$(grep -wo "\\$\S\S*\\$" test2 | sort -u | tr '$' '\n'); 
user$ echo $list
FRUIT TIMES
user$ for thing in ${list[@]}; do sed -i 's/\$\$'$thing'\$\$/'$"${!thing}"'/g' test2; done
user$ cat test2 
The APPLE is good for health. Everyone should eat APPLE DAILY.

Here is a way to do this in a single gnu-awk command using ENVIRON array, without involving any other utility.

s='The $$FRUIT$$ is good for health. Everyone should eat $$FRUIT$$ $$TIMES$$'
export FRUIT='APPLE'
export TIMES='DAILY'

awk '{
   while (match($0, /\$\$([_[:alnum:]]+)\$\$/, a))
      $0 = substr($0, 1, RSTART-1) ENVIRON[a[1]] substr($0, RSTART+RLENGTH)
} 1' <<< "$s"

The APPLE is good for health. Everyone should eat APPLE DAILY

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM