• Uncategorized

About bash : How-to-use-variables-in-sed-command

Question Detail

I have file called “text_file1.txt” and the content in the file is
“subject= /C=US/O=AAA/OU=QA/OU=12345/OU=TESTAPP/”

Now what i want to achieve is to the content to be like below:
“subject= /C=US/O=AAA/$$$QA/###12345/@@@TESTAPP/”

when i execute the below piece of code:

#! /bin/ksh
OU1="QA"
OU2=12345
OU3="TESTAPP"
`sed -i "s/OU=$OU1/$$$\${OU1}/g" text_file1.txt`
`sed -i "s/OU=$OU2/###\${OU2}/g" text_file1.txt`
`sed -i "s/OU=$OU3/@@@\${OU3}/g" text_file1.txt`
content=`cat text_file1.txt`
echo "content:$content"

i get the output like this:

content:subject= /C=US/O=Wells Fargo/2865528655{OU1}/###12345/@@@TESTAPP/CN=03032015_CUST_2131_Unix_CLBLABB34C02.wellsfargo.com

only this command “sed -i "s/OU=$OU1/$$$\${OU1}/g" text_file1.txt” is not working as expected.Can anyone please suggest some idea on this?

Thanks in advance.

Question Answer

Two things play into this:

  1. You have to escape $ (i.e., use \$) in doubly-quoted shell strings if you want a literal $, and
  2. \ does not retain its literal meaning when it comes before a $ inside backticks (that is to say, inside backticks, \$ becomes just $).

When you write

`sed -i "s/OU=$OU1/$$$\${OU1}/g" text_file1.txt`

because the command is in backticks, you spawn a subshell with the command

sed -i "s/OU=$OU1/$$$${OU1}/g" text_file1.txt

Since $$$$ is inside a doubly-quoted string, variable expansion takes place, and it is expanded as two occurrences of $$ (the process ID of the shell that’s doing the expansion). This means that the code sed sees is ultimately

s/OU=QA/1234512345{OU1}/g

…if the process ID of the spawned subshell is 12345.

In this particular case, you don’t need the command substitution (the backticks), so you could write

sed -i "s/OU=$OU1/\$\$\$${OU1}/g" text_file1.txt

However, using shell variables in sed code is always a problem. Consider, if you will, what would happen if OU1 had the value /; e rm -Rf * # (hint: GNU sed has an e instruction that runs shell commands). For this reason, I would always prefer awk to do substitutions that involve shell variables:

cp text_file1.txt text_file1.txt~
awk -v OU1="$OU1" '{ gsub("OU=" OU1, "$$$" OU1) } 1' text_file1.txt~ > text_file1.txt

This avoids code injection problems by not treating OU1 as code.

If you have GNU awk 4.1 or later,

awk -v OU1="$OU1" -i inplace  '{ gsub("OU=" OU1, "$$$" OU1) } 1' text_file1.txt

can do the whole thing without a (visible) temporary file.

Does this help as a start?

echo ''
OU1="QA"
echo "subject= /C=US/O=AAA/OU=${OU1}/OU=12345/OU=TESTAPP/" \
| sed -e "s|/OU=${OU1}/|/OU=\$\$\$${OU1}/|g"

The result is:

subject= /C=US/O=AAA/OU=$$$QA/OU=12345/OU=TESTAPP/

(You are mixing up the use of $ signs .)

You must be careful when putting $ inside double quotes.

sed -i "s/OU=$OU1/"'$$$'"${OU1}/g" text_file1.txt

Example:

$ OU1="QA"
$ echo 'OU=QA' | sed "s/OU=$OU1/"'$$$'"${OU1}/g"
$$$QA

You may also like...

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.