1

I'm trying to use sed as root to alter the default PS1.

The first 2 lines were just to make sure I had the syntax structured right and to see if the quotation marks made a difference, running them consecutively allows me to change a comment near the top of the file and then change it back. Opening the file in nano confirms the changes are effective, which should rule out 'write permissions'.

sed -i 's/If not running interactively,/stringtoreplaceitwith/' /etc/skel/.bashrc
sed -i "s/stringtoreplaceitwith/If not running interactively,/" /etc/skel/.bashrc
sed -i "s/\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ /Replace PS1/" /etc/skel/.bashrc

I'm not sure if it's something else about the string's structure, but for some reason, it's not finding what I'd like to substitute.

\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ 

(with a trailing blank).

sedPS1

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
TurtleWolfe
  • 125
  • 1
  • 12
  • Changing what is in your .bashrc makes no difference until it is sourced again. To change the prompt on the fly you need to set the PS1 prompt, e.g. set `PS1='whatever you want for PS1`, or you can also `export PS1='whatever you want for PS1`. You have to `source` a file containing the new prompt as you cannot affect the current shell from a subshell. (recall the rule, "A child process cannot affect the environment of its parent.") – David C. Rankin Apr 05 '19 at 17:30
  • 2
    Mind that constructs like `[]` have special meanings in a sed expression. This denotes a range. I guess the best option is to open the rc file in vim and do the change manually. Ah ! I see you've escaped those. But isn't the whole process quite painful? – sjsam Apr 05 '19 at 17:30
  • 1
    Further `/etc/skel/.bashrc` is only used to create the default `.bashrc` when creating a new user with `useradd`. You can change that file all you want and it will have no affect on existing users. – David C. Rankin Apr 05 '19 at 17:35
  • Even if it's not affecting the shell, wouldn't it update what's in the file? Ultimately I'd like to add it to a script that automates building the server.. I've already done it manually, but the ultimate goal is to make it part of the original automation script that builds the server. Is there a way to escape the brackets or should I be trying to use something besides sed? – TurtleWolfe Apr 05 '19 at 17:36

1 Answers1

1

Your problem is due to quoting and escaping. Let's reduce the string you're trying to substitute to just this:

\w\[\033[00m\]\$

(with a trailing blank) – this contains all the difficulties, but is less verbose.

To match this, we have to

  • escape all the backslashes: \w becomes \\w etc.
  • escape [ and ], because they're special to sed: [ becomes \[, and \[ becomes \\\[ (escaped backslash, escaped [)
  • escape $: \$ becomes \\\$

Then, we have to use single quotes around our sed command so the shell doesn't modify the string:

$ sed 's/\\w\\\[\\033\[00m\\\]\\\$ /Replace PS1/' <<< '\w\[\033[00m\]\$ '
Replace PS1

It can also work with double quotes, but then we have to add another round of escaping for the shell: \[ becomes \\\[ (escaped for sed) becomes \\\\\\[ (escaped for the shell), and so on.

$ sed "s/\\\\w\\\\\\[\\\\033\\[00m\\\\\\]\\\\\\$ /Replace PS1/" <<< '\w\[\033[00m\]\$ '
Replace PS1

Double quoting only makes sense if you're using variables, though, for obvious reasons.

Finally, for your actual string:

$ echo '\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' \
    | sed 's/\\\[\\033\[01;32m\\\]\\u@\\h\\\[\\033\[00m\\\]:\\\[\\033\[01;34m\\\]\\w\\\[\\033\[00m\\\]\\\$ /Replace PS1/'
Replace PS1
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116