Reputation: 353
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?
Upvotes: 8
Views: 7100
Reputation: 14910
How about this:
sed -i 's/^PS1.*$/PS1=SINGLEQUOTESLASH[SLASHe[1;32mSLASH][SLASHu@SLASHh SLASHW]SLASH$SLASH[SLASHe[0mSLASH]SINGLEQUOTE/g' /etc/skel/.bashrc
sed -i "s/SINGLEQUOTE/'/g" /etc/skel/.bashrc
sed -i "s/SLASH/\\/g" /etc/skel/.bashrc
Doing it in two passes is less efficient, but a few more microseconds is unnoticeable to most people.
Upvotes: 1
Reputation: 353
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
Upvotes: 5
Reputation: 58463
This might work for you:
echo "PS1=abc" |
sed 's/^PS1.*$/PS1='\''\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\]'\''/'
PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\]'
Upvotes: 4
Reputation: 36049
Use a sed script file with sed -f
. This alternative is not pretty, too, because it means having an additional file lying around, but at least you avoid shell escapes.
Upvotes: 1