I want to edit a file via a sed script in a bash script. I want this to be easy to maintain later; easy to understand and modify. The replacement string looks like:
PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\]'
In a perfect world, it would like this:
sed -i "s/^PS1.*$/PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\]'/g" /etc/skel/.bashrc
The problem is that bash and sed are stripping out the \
giving the following result in the file:
PS1='[e[1;32m][@h W]$[e[0m]'
Obviously single quotes can't be used. A brute force solution is to use escapes, but for this to work I get a really ugly looking line:
sed -i "s/^PS1.*$/PS1='\\\\[\\\\e[1;32m\\\\][\\\\u@\\\\h \\\\W]\\\\$\\\\[\\\\e[0m\\\\]'/g" /etc/skel/.bashrc
I want the script to be readable and self contained (not using external files). Any alternatives to the above?
Put a backslash before $. */[\]^ and only those characters (but not inside bracket expressions).
Use single quotes for sed and you can get away with two backslashes. echo "sample_input\whatever" | sed 's/\\/\//' Hopefully someone will come up with the correct explanation for this behavior.
Escape characters are used to remove the special meaning from a single character. A non-quoted backslash, \, is used as an escape character in Bash.
You need to escape the / as \/ . The escape ( \ ) preceding a character tells the shell to interpret that character literally.
Bash's printf can add the necessary escapes, leaving the string to be inserted in an readable, editable form.
sed -i "s/^PS1.*$/$(printf "%q" "PS1='\[\e[1;32m\][\u@\h \W]$\[\e[0m\]'")/g" /etc/skel/.bashrc
Not trying to stick it all on one line makes the whole thing clearer.
REPL=$(printf "%q" "PS1='\[\e[1;32m\][\u@\h \W]$\[\e[0m\]'")
sed -i "s/^PS1.*$/$REPL/g" /etc/skel/.bashrc
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With