I'm trying to automate switching out a bash prompt for another in .bashrc

Original String:

PS1='${debian_chroot:+($debian_chroot)}\[\033[01;31m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '

Replacement Strings:

IPeth0=$(Adr=$(ifconfig eth0 |grep inet); echo $Adr | awk '{print $2}' | cut -c 6- )
PS1='\d \t \[\e[0;31m\]\u@$IPeth0\[\e[0;32m\]:\[\e[0;36m\]\w# \[\e[m\] '

One of many poor attempts at writing bash to do so:

original="PS1='${debian_chroot:+($debian_chroot)}\[\033[01;31m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '"
replacement="PS1='\d \t \[\e[0;31m\]\u@$IPeth0\[\e[0;32m\]:\[\e[0;36m\]\w# \[\e[m\] '" 
ipvar="IPeth0=$(Adr=$(ifconfig eth0 |grep inet); echo $Adr | awk '{print \$2}' | cut -c 6- )"

cp ~/.bashrc ~/.bashrc.bak
sed -e 's/$original/$replacement/g' ~/.bashrc

I've tried double escaping all of the characters because I know sed needs '\','/', and '&' escaped. I just can't seem to wrap my head around this one.

I didn't even bother trying to get the IP line in there right away because I couldn't replace the first line.

If there are any better methods for this type of automation please let me know.

1 Answer 1


Here are a couple of approaches (well, 2½):

  • If you’re interested in being able to incrementally modify PS1 settings that follow a general template,

    • Create a file that contains only the PS1=… line.
    • Write sed commands to edit it, piece by piece; e.g.,
      • sed -e 's/${debian_chroot:+($debian_chroot)}/\\d \\t /'
      • sed -e 's/\\033/\\e/g'
      • etc.
    • You might find it easier to debug these smaller, simpler commands.  When you’ve gotten them all working, it should be straightforward to stitch them together.
    • Have you looked at the value of $original?  E.g., have you done
              printf "%s\n" "$original"
      ?  Remember, when you say something like

      "The quick brown fox 'jumps over' the lazy dog."

      The entire string is in double quotes.  So when you say

      "Humpty '$var' Dumpty"

      The $var gets expanded, because it’s in double quotes.

      Now look at your original string:


      The ${debian_chroot:+($debian_chroot)} gets expanded when you make that assignment.  So that’s a problem.

  • If you just want to change PS1 to your new value, regardless of what’s already there, don’t try to chisel down the statue of the fox and then add clay in the hopes of creating a statue of a dog; just blow away the existing assignment and replace it, using sed’s c (change) command, which replaces one group of one or more lines with another group of one or more lines:

    sed -e $'/^PS1=/c\
    IPeth0=$(Adr=$(ifconfig eth0 |grep inet); echo $Adr | awk \'{print $2}\' | cut -c 6- )\
    PS1=\'\d \t \[\e[0;31m\]\u@$IPeth0\[\e[0;32m\]:\[\e[0;36m\]\w# \[\e[m\] \''

    I put the entire sed command string into $'…' so I could use \' to get raw ' characters into the string.  If you prefer, you can use the tried and true

    '$not_a_variable …'"… please don't try to expand those …"'… $not_a_variable'

    (quote alternation) technique.

  • A variant on the above is

    sed -e $'/^PS1=/{s/^/# /; a\
    IPeth0=$(Adr=$(ifconfig eth0 |grep inet); echo $Adr | awk \'{print $2}\' | cut -c 6- )\
    PS1=\'\d \t \[\e[0;31m\]\u@$IPeth0\[\e[0;32m\]:\[\e[0;36m\]\w# \[\e[m\] \'

    which comments out the existing definition (s/^/# /) and appends the new lines with the a command.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .