views:

8093

answers:

4

In my bash script I have an external (received from user) string, which I should use in sed pattern.

REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"

How can I escape the $REPLACE string so it would be safely accepted by sed as a literal replacement?

NOTE: The KEYWORD is a dumb substring with no matches etc. It is not supplied by user.

A: 

Here is an example of an AWK I used a while ago. It is an AWK that prints new AWKS. AWK and SED being similar it may be a good template.

ls | awk '{ print "awk " "'"'"'"  " {print $1,$2,$3} " "'"'"'"  " " $1 ".old_ext > " $1 ".new_ext"  }' > for_the_birds

It looks excessive, but somehow that combination of quotes works to keep the ' printed as literals. Then if I remember correctly the vaiables are just surrounded with quotes like this: "$1". Try it, let me know how it works with SED.

Alex
+3  A: 

The only three literal characters which are treated specially in the replace clause are / (to close the clause), \ (to escape characters, backreference, &c.), and & (to include the match in the replacement). Therefore, all you need to do is escape those three characters:

sed "s/KEYWORD/$(echo $REPLACE | sed -e 's/\\/\\\\/g' -e 's/\//\\\//g' -e 's/&/\\\&/g')/g"

Example:

$ export REPLACE="'\"|\\/><&!"
$ echo fooKEYWORDbar | sed "s/KEYWORD/$(echo $REPLACE | sed -e 's/\\/\\\\/g' -e 's/\//\\\//g' -e 's/&/\\\&/g')/g"
foo'"|\/><&!bar
Ben Blank
Also a newline, I think. How do I escape a newline?
Alexander Gladysh
A: 

Just escape everything in the REPLACE varible:

echo $REPLACE | awk '{gsub(".", "\\\\&");print}'
PEZ
Escaping everything is not a good idea. See my post for details.
Pianosaurus
+5  A: 
Pianosaurus
+1, I didn't think of backrefs and stuff.
PEZ