Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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?

share|improve this question
add comment

4 Answers

up vote 3 down vote accepted

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')"
share|improve this answer
    
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
add comment

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"
share|improve this answer
add comment

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
share|improve this answer
    
Also a very nice solution although I went with the sed way. –  pmr Aug 10 '12 at 13:22
add comment

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

share|improve this answer
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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.