Search code examples
stringshellvariablesunix

Storing escape characters in unix variable


I am extracting a part from an existing file and storing it as a string in a variable.The string looks something like this.

var="*a<br>*b<br>*c"

Now as * is a special character in unix it doesnot work in further operations(like sed,grep) until I put an escape character infront of every *

Thats why,I am doing something like this -

echo $var | sed 's/\*/\\*/g'

On running this command in bash we get

echo $var | sed 's/\*/\\*/g'

\*a<br>\*b<br>\*c

which is the desired output,but when I try to store this in a variable, I am getting back my original variable like so

var=`echo $var | sed 's/\*/\\*/g'`
echo $var

*a<br>*b<br>*c

I am assuming this happens because the variable ignores the backslashes interpreting them as escape characters. How can I retain the backslashes and store them as in a variable?


Solution

  • The problem is caused by backticks. Use $( ) instead, and it goes away:

    var="*a<br>*b<br>*c"
    var=$(printf '%s\n' "$var" | sed 's/\*/\\*/g')
    printf '%s\n' "$var"
    

    (Why is this problem caused by backticks? Because the only way to nest them is to escape the inner ones with backslashes, so they necessarily change how backslashes behave; whereas $( ), because it uses different starting and ending sigils, can be nested natively).


    That said, if your shell is one (like bash) with ksh-inspired extensions, you don't need sed at all here, as the shell can perform simple string replacements natively via parameter expansion:

    var="*a<br>*b<br>*c"
    printf '%s\n' "${var//'*'/'\*'}"
    

    For background on why this answer uses printf instead of echo, see Why is printf better than echo? at [unix.se], or the APPLICATION USAGE section of the POSIX specification for echo.