2

Currently I use:

sed -i -e "5a\\
${text}" $filename

to append something to a certain line, where the variable text contains a string such as "\epsilon".

When using

echo -E $text

the string is displayed just fine, but when I expand it in the string I pass to sed, all escape characters get expanded and the result is not what I would want.

How can I get sed to use the raw contents of that string without escaping anything?

pmr
  • 123

4 Answers4

4

The sed command a\ interprets escapes, so you need to duplicate backslashes in the string you are interpolating. Try this:

sed -e "5a\\
$(echo -E "$text" | sed -e 's/\\/\\\\/g')"
angus
  • 12,321
  • 3
  • 45
  • 40
  • Thanks. I'll probably need to add escaping of $ as well. How many other special symbols that require escaping are possible for a bash string? – pmr Aug 10 '12 at 12:04
  • No, the shell doesn't do recursive interpolation. If you have a='AA' and b='this is $a', then echo $b will just print this is $a. Once you make echo output the correct string, you only need to worry about sed, and sed only interprets backslashes, which is taken care of with the inner sed. That's all. – angus Aug 10 '12 at 13:03
2

Quoting is tricky. I recommend using a tool that doesn't require you to add additional quotes, such as awk or perl. These two tools allow you to pass parameters on the command line or through the environment and use them in text manipulations. With Perl:

export text
perl -i -pe '$_ .= "$ENV{text}\n" if $. == 5' "$filename"

With awk, you need to do the file moving manually:

tmp=$(TMPDIR=$(dirname -- "$filename") mktemp)
awk -v text="$text" '{print} NR==5 {print text}' <"$filename" >"$tmp" &&
mv -- "$tmp" "$filename"
1

You can generally apply escaping with printf "%q", try this:

text='\epsilon'
echo -e "$text"
silon

with %q:

text=$(printf "%q" '\epsilon')
echo -e "$text"
\epsilon
Thor
  • 17,182
-1

As I am not a sed master, I find it easier to explain with echo.

Use single quotes instead of double quotes.

example1:

echo "one\\two"
one\two

example2:

echo 'one\two'
one\two

So, by using the example2 way, you don't have to escape anythin. The string inside the single quotes 's\t\r\i\n\g' is interpreted as it is. (The \ character does not work as an escape character)

source: one

fromnaboo
  • 6,932
  • 1
    That is useless. As you can see I need to expand a variable. That wouldn't happen if I were to use single quote escapes. – pmr Aug 10 '12 at 12:03