Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sed search and replace strings containing / [duplicate]

Tags:

bash

sed

I am having trouble figuring out how to use sed to search and replace strings containing the / character in a text file /etc/myconfig.

For instance, in my existing text file, I have:

myparam /path/to/a argB=/path/to/B xo 

and I want this replaced by:

myparam /path/to/c argB=/path/to/D xo 

I attempted doing this in bash:

line='myparam /path/to/a argB=/path/to/B xo' line_new='myparam /path/to/c argB=/path/to/D xo' sed -i 's/$line/$line_new/g' /etc/myconfig 

But nothing happens.

Attempting

grep -rn "$line" /etc/myconfig 

does return me 'myparam /path/to/a argB=/path/to/B xo' though.

What's the correct way to express my sed command to execute this search and replace and correctly deal with the / command? (I reckon that the / character in my strings are the ones giving me the problem because I used a similar sed command to search and replace another line in the text file with no problems and that line does not have a / character.

like image 210
Calvin Cheng Avatar asked Apr 25 '12 05:04

Calvin Cheng


People also ask

Does sed support multiline replacement?

Sometimes it requires to replace multiple lines of a file with any particular character or text. Different commands exist in Linux to replace multiple lines of a file. `sed` command is one of them to do this type of task.


2 Answers

Don't escape the backslashes; you'll confuse yourself. Use a different symbol after the s command that doesn't appear in the text (I'm using % in the example below):

line_old='myparam /path/to/a argB=/path/to/B xo' line_new='myparam /path/to/c argB=/path/to/D xo' sed -i "s%$line_old%$line_new%g" /etc/myconfig 

Also, enclose the whole string in double quotes; using single quotes means that sed sees $line (in the original) instead of the expanded value. Inside single quotes, there is no expansion and there are no metacharacters. If your text can contain almost any plain text character, use a control character (e.g. control-A or control-G) as the delimiter.

Note that the use of -i here mirrors what is in the question, but that assumes the use of GNU sed. BSD sed (found on Mac OS X too) requires a suffix. You can use sed -i '' … to replace in situ; that does not work with GNU sed. To be portable between the two, use -i.bak; that will work with both — but gives you a backup file that you'll probably want to delete. Other Unix platforms (e.g. AIX, HP-UX, Solaris) may have variants of sed that do not support -i at all. It is not required by the POSIX specification for sed.

like image 79
Jonathan Leffler Avatar answered Sep 18 '22 23:09

Jonathan Leffler


This might work for you:

sed -i "s|$line|$line_new|g" /etc/myconfig 

You must use "'s so that the $line and $new_line are interpolated. Also use | or any character not found in the match or replacement strings as a delimiter.

like image 23
potong Avatar answered Sep 20 '22 23:09

potong