0

I'm replacing a string with another string that includes escaped quotes:

echo "replace FOO" | sed -e "s~FOO~test\\\"test~g"

What I would expect is to see replace test\"test. Instead I see replace test"test.

How can I get sed to include my escape sequence?

0

2 Answers 2

1

Backslash is an escape character both within double quotes and in the sed replacement. So with "\\\"", sed sees \" which it takes to mean "

Try single quotes:

echo "replace FOO" | sed -e 's~FOO~test\\"test~g'

or doubly escape:

echo "replace FOO" | sed -e "s~FOO~test\\\\\"test~g"
4
  • I'm actually replacing the inner text with an environment variable, which only works with double quotes as far as I can tell. Is there a way to insert an environment variable using single quotes? Commented Apr 2, 2020 at 3:17
  • end the single quotes, insert "$var", then open the single quotes again: 's~FOO~test\\"te'"$var"'st~g'
    – guest
    Commented Apr 2, 2020 at 3:21
  • Unfortunately my variable contains double and single quotes (it's JSON), which seems to trip it all up. Commented Apr 2, 2020 at 3:23
  • Thanks - you put me on the right track. I had to super-escape my escaped quotes with sed -e 's~\\"~\\\\"~g'. Commented Apr 2, 2020 at 3:48
0

An \ is special both to the shell (which removes one) and to sed (which removes another. To get sed to understand what is actually needed, you need to give sed this string:

s~FOO~test\\\"test~g

Which sed will convert to test\"test, which is what you need.

Then the shell should receive either a double quoted string with every \ doubled and the " quoted \" (that's 7 \):

sed "s~FOO~test\\\\\\\"test~g"

Which will be converted by the shell to "s~FOO~test\\"test~g" and sed will use s~FOO~test\"test~g.

Or, a bit simpler, use single quotes ' (only 3 \):

sed 's~FOO~test\\\"test~g'

Added

In comments you said: "I'm actually replacing the inner text with an environment variable" and "Unfortunately my variable contains double and single quotes"

Well, then, set your variable to exactly what you want sed to receive, example:

$ var='test\'\''test\"test'; echo "$var"
test\'test\"test

And, if the slash is only used to escape the quote, modify the variable with this (Assuming bash, a portable solution needs more work):

$ echo "${var//\\/\\\\\\}"
test\\\'test\\\"test

Which will convert one \ (written as \\) to three \ (written as \\\\\\).

And the replacement will work as this:

$ echo "replace FOO" | sed -e 's~FOO~'"${var//\\/\\\\\\}"'~g'

This is not a general solution for any \ in the variable.

General solution

A general solution would need two passes to double all \ and then escape every double quote:

$ var='test\'\''test\"test    aa\\\"bb\\\\\'\''cc\'\'
$ echo "$var"
test\'test\"test    aa\\\"bb\\\\\'cc\'

Then modify var:

$ var=${var//\\/\\\\}; var=${var//\"/\\\"}; echo "$var"
test\\'test\\\"test    aa\\\\\\\"bb\\\\\\\\\\'cc\\'

And the replacement will work like this:

$ echo "replace FOO" | sed -e 's~FOO~'"$var"'~g'
replace test\'test\"test    aa\\\"bb\\\\\'cc\'

Exactly the original content of the variable var.

You must log in to answer this question.

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