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
.