146

I am using the below code for replacing a string inside a shell script.

echo $LINE | sed -e 's/12345678/"$replace"/g'

but it's getting replaced with $replace instead of the value of that variable.

Could anybody tell what went wrong?

3

12 Answers 12

204

If you want to interpret $replace, you should not use single quotes since they prevent variable substitution.

Try:

echo $LINE | sed -e "s/12345678/${replace}/g"

Transcript:

pax> export replace=987654321
pax> echo X123456789X | sed "s/123456789/${replace}/"
X987654321X
pax> _

Just be careful to ensure that ${replace} doesn't have any characters of significance to sed (like / for instance) since it will cause confusion unless escaped. But if, as you say, you're replacing one number with another, that shouldn't be a problem.

Sign up to request clarification or add additional context in comments.

7 Comments

i dont want the quotes put in.i want one number to be replaced with other
paxdiablo: set is also not necessary (and how were you going to use it anyway?). Just replace=987654321.
I usually always use export to ensure that variables are set for children but, as you say, you could just as easily avoid it. However, the use or not of export is irrelevant here (a style issue) and has no effect on the actual answer, which is how to use variables within a sed command.
This solution doesn't seem to be working with the -i option. Would you know why? or how to make it work?
Maybe also point out that switching from single to double quotes requires any $ or ` in the sed script to be escaped with a backslash, to protect it from the shell's substitution mechanism for double-quoted strings.
|
104

you can use the shell (bash/ksh).

$ var="12345678abc"
$ replace="test"
$ echo ${var//12345678/$replace}
testabc

5 Comments

May want to mention that's bash-specific (and ksh?). Probably not of import to most people but some of us are still forced to work on ancient UNIXen :-)
Beware, this also fails on dash, which is /bin/sh on many modern Linuxes.
why need two forward slashes after the "var"? one should be enough according to my test.
You need to slashes if you want global replace, rather than the first instance.
For a bit of fun - in order to replace a forward slash in a string, you will need to use the syntax ${var//\//replace}. foo="apple/banana; echo "${foo//\//#}" gives apple#banana
43

Not specific to the question, but for folks who need the same kind of functionality expanded for clarity from previous answers:

# create some variables
str="someFileName.foo"
find=".foo"
replace=".bar"
# notice the the str isn't prefixed with $
#    this is just how this feature works :/
result=${str//$find/$replace}
echo $result    
# result is: someFileName.bar

str="someFileName.sally"
find=".foo"
replace=".bar"
result=${str//$find/$replace}
echo $result    
# result is: someFileName.sally because ".foo" was not found

1 Comment

You can find the docs in linuxcommand.org/lc3_man_pages/bash1.html. Look for ${parameter/pattern/string}
23

Found a graceful solution.

echo ${LINE//12345678/$replace}

Comments

12

Single quotes are very strong. Once inside, there's nothing you can do to invoke variable substitution, until you leave. Use double quotes instead:

echo $LINE | sed -e "s/12345678/$replace/g"

Comments

9

Let me give you two examples.

  • Using sed:
#!/bin/bash
LINE="12345678HI"
replace="Hello"
echo $LINE | sed -e "s/12345678/$replace/g"
  • Without Using sed:
LINE="12345678HI"
str_to_replace="12345678"
replace_str="Hello"
result=${str//$str_to_replace/$replace_str}
echo $result

Hope you will find it helpful!

1 Comment

finaly one tt works
5
echo $LINE | sed -e 's/12345678/'$replace'/g'

you can still use single quotes, but you have to "open" them when you want the variable expanded at the right place. otherwise the string is taken "literally" (as @paxdiablo correctly stated, his answer is correct as well)

1 Comment

This has the problem that using $replace outside of any quotes will cause the shell to perform whitespace tokenization and wildcard expansion on the value. This will appear to work with simple values, but could blow up dramatically on nontrivial strings. Don't use this in production code.
3

To let your shell expand the variable, you need to use double-quotes like

sed -i "s#12345678#$replace#g" file.txt

This will break if $replace contain special sed characters (#, \). But you can preprocess $replace to quote them:

replace_quoted=$(printf '%s' "$replace" | sed 's/[#\]/\\\0/g')
sed -i "s#12345678#$replace_quoted#g" file.txt

Comments

2

use @ if you want to replace things like /. $ etc.

result=$(echo $str | sed "s@$oldstr@$newstr@g")

the above code will replace all occurrences of the specified replacement term if you want, remove the ending g which means that the only first occurrence will be replaced.

Comments

0

I had a similar requirement to this but my replace var contained an ampersand. Escaping the ampersand like this solved my problem:

replace="salt & pepper"
echo "pass the salt" | sed "s/salt/${replace/&/\&}/g"

Comments

-1

Use this instead

echo $LINE | sed -e 's/12345678/$replace/g'

this works for me just simply remove the quotes

Comments

-2

I prefer to use double quotes , as single quptes are very powerful as we used them if dont able to change anything inside it or can invoke the variable substituion .

so use double quotes instaed.

echo $LINE | sed -e "s/12345678/$replace/g"

1 Comment

Is this any different from Dave's answer?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.