Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have created a shell script which takes a string as input. If the string contains $ or &, then I need to replace those characters with \$ and \&. I could done that with sed command. After this I want to replace a word in a particular text file with that corresponding string.

Please see this section for more clarification.

This is my file.

test.txt

hello my root password is root.

Now, I want to change the word root with a string. The string can be anything which may include special characters like $ or &.

If I want to replace root with the string my&rootpa$$, then it should look like my\&rootpa\$\$ in text file.

This is my shell scipt

#!/bin/bash
dothis(){
    rootpass=$(echo "$1" | sed -r 's/\$/\\$/g');
    rootpass=$(echo "$rootpass" | sed -r 's/\&/\\&/g');
    echo $rootpass;
    sed -i "s/root/$rootpass/g" test.txt
}
dothis "my&rootpa$$";

This script works properly upto echo $rootpass, which means when I echo the string it will display my\&rootpa\$\$.

But in the file it looks my&rootpa$$ instead of my\&rootpa\$\$. What's wrong with the script?

Please advice.

share|improve this question
    
Please don't cross port to multiple SE sites. I see you have an answer on Super User that is correct though. – Iain Jan 22 '14 at 7:55
    
Hi lain, I have posted the same question at SuperUser, askubuntu also. I was in a bit hurry to get the answer. Is there any issues in this ? – Uvais Ibrahim Jan 22 '14 at 10:14
    
Yes, please don't do it as it fragments the answers and is frowned upon. Also as you found out you can make errors when copying them which is a nuisance. Just don't do it. – Iain Jan 22 '14 at 10:16
    
Thanks Lain for your concern. I am beginner in all these. – Uvais Ibrahim Jan 22 '14 at 10:34
up vote 2 down vote accepted

There's an extra layer of quoting lacking. In sed & has a special meaning in the replacement (stands for the matching string). So to insert a literal & you'd escape it once, and to insert a literal \&, you'd escape the backslash (\\) and the ampersand (\\&), same for the backslash before $. That gives you:

#!/bin/bash
dothis(){
    rootpass="${1//\$/\\\\$}"
    rootpass="${rootpass//&/\\\\\&}"
    echo $rootpass
    sed -i "s/root/$rootpass/g" test.txt
}
dothis 'my&rootpa$$';
share|improve this answer
    
Not working for me: ${$1//&/\\\\\&}: bad substitution – Crisboot Jan 18 at 13:23

You should change this line:

dothis "my&rootpa$$";

to

dothis "my&rootpa\$\$";

or using quote instead of double quotes:

dothis 'my&rootpa$$';

In your case, $$ in string my&rootpa$$ will be expanded to PID of script itself.

share|improve this answer
    
As the OP says everything OK up to the last sed command at which point $rootpass is my\&rootpas\$\$ so the problem variable expansion. – Iain Jan 22 '14 at 7:32

This "dothis "my&rootpa$$" uses double quotes and the "$$" at the end will be expanded to the current PID. When I execute your script, this happens:

 $ ./a.sh 
 my\&rootpa3595

...since "3595" happens to be the PID of the script. When you use single quotes (' '), the string you expected is printed:

 $ tail -1 a.sh 
 dothis 'my&rootpa$$';

 $ ./a.sh 
 my\&rootpa\$\$
share|improve this answer
    
Note the last paragraph of the question which show that the $$ isn't being expanded... Take a look at revision 1 of the OPs question it shows an incorrect sed command, I suspect other transcription errors too. – Iain Jan 22 '14 at 7:41
    
NOte also that you haven't done the final sed which is the problem. – Iain Jan 22 '14 at 7:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .