PS1 prompt differences between bash versions 3.2.25 v 4.1.2
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
PS1 prompt differences between bash versions 3.2.25 v 4.1.2
I have a preferred bash prompt layout and have tried to apply it to 2 different systems at work. However, it does not perform the same in both environments.
As listed in the question, one is running 3.2.25 and the other 4.1.2.
You may have guessed that it works correctly on the machine with the higher version of bash.
My problem is I cannot see what I have introduced that would not be understood by both versions.
So, here is the bashrc:
Code:
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific aliases and functions
# Colours
RED='\[\e[1;31m\]'
GREEN='\[\e[1;32m\]'
YELLOW='\[\e[1;33m\]'
BLUE='\[\e[1;34m\]'
CYAN='\[\e[1;36m\]'
NORM='\[\e[m\]'
# PS1 pieces
DATE='[\D{%d-%m-%Y} \t]'
LPATH='[\w]'
DB_USER='[none]'
DB_COL=BLUE
WHERE='[\u@\h]'
#alias ls='ls --group-directories-first --time-style=+"%d.%m.%Y %H:%M" --color=auto -F'
alias ls='ls --time-style=+"%d.%m.%Y %H:%M" --color=auto -F'
alias ll='ls -l'
alias la='ls -a'
alias lla='ll -a'
alias lh='ll -h'
alias ld='ll -d'
alias grep='grep --color=tty -d skip'
alias fgrep='grep -F'
alias egrep='grep -E'
alias df='df -h' # human-readable sizes
alias free='free -m' # show sizes in MB
alias less='less -XRFmx2'
alias more=less
# Less Colors for Man Pages
export LESS_TERMCAP_mb=$'\E[1;33m' # begin blinking
export LESS_TERMCAP_md=$'\E[1;33m' # begin bold
export LESS_TERMCAP_me=$'\E[0m' # end mode
export LESS_TERMCAP_so=$'\E[1;32;5;246m' # begin standout-mode - info box
export LESS_TERMCAP_se=$'\E[0m' # end standout-mode
export LESS_TERMCAP_us=$'\E[04;1;36m' # begin underline
export LESS_TERMCAP_ue=$'\E[0m' # end underline
# History settings
export HISTSIZE=10000
export HISTFILESIZE=${HISTSIZE}
export HISTCONTROL=ignoreboth:erasedups
export HISTIGNORE=ls:la:ll:lh:cd:fg*:jobs:exit:history*:df:sqlplus*
export HISTTIMEFORMAT='%F %T'
# Set ORACLE_HOME and add to path
export ORACLE_HOME=/u01/app/oracle/product/11.2.0/rms
export PATH=$ORACLE_HOME/bin:$ORACLE_HOME/OPatch:$PATH
# functions
set_db()
{
local -a la_db_list
local ls_db
la_db_list=($(awk -F: 'NF == 3 && /^[[:alpha:]]/{print $1}' /etc/oratab))
if (( ${#la_db_list[*]} > 1 ))
then
trap 'echo -en "\e[1;33m\n\nYou MUST pick an entry. Press enter to see prompt\e[m"' INT TERM
PS3="$(echo -en "\e[1;36m\nPlease select a database from the list: \e[m")"
select ls_db in "${la_db_list[@]}"
do
if [[ -n "$ls_db" ]]
then
if [[ "$ls_db" =~ prd ]]
then
DB_COL=RED
else
case $REPLY in
1) DB_COL=BLUE;;
2) DB_COL=GREEN;;
3) DB_COL=YELLOW;;
4) DB_COL=CYAN;;
esac
fi
DB_USER="[$ls_db]"
ORACLE_SID=$ls_db
break
fi
echo -e "\e[1;33m\nPlease select from the numbers provided"
done
else
if [[ -n "${la_db_list[@]}" ]]
then
[[ "${la_db_list[0]}" =~ prd ]] && DB_COL=RED || DB_COL=GREEN
DB_USER="[${la_db_list[0]}]"
ORACLE_SID=${la_db_list[0]}
else
return
fi
fi
# Use built in oracle script to set environment
ORAENV_ASK=NO
. oraenv
# Oracle exports
export SQLPATH=~/.sql
# Oracle aliases
#alias sqlplus='rlwrap -i sqlplus'
alias sss='sqlplus / as sysdba'
# Exported variables
export TNS_ADMIN=$ORACLE_HOME/network/admin
echo -e '\e[1;32m\nYou can change the environment using set_db at any time'
} #set_db
if shopt -q login_shell
then
set_db
fi
if [[ ${EUID} == 0 ]] ; then
PS1="$YELLOW$DATE$GREEN$LPATH$NORM\n$BLUE$DB_USER$RED$WHERE\$ "
else
PS1="$YELLOW$DATE$GREEN$LPATH$NORM\nnonex$NORM$WHERE\$ "
# PS1="$YELLOW$DATE$GREEN$LPATH$NORM\n$DB_USER$NORM$WHERE\$ "
# PS1="$YELLOW$DATE$GREEN$LPATH$NORM\n${!DB_COL}$DB_USER$NORM$WHERE\$ "
fi
The unusual behaviour I am getting occurs when I try to search for a previous command I have used, pressing ctrl+r to search.
On the 4.1.2 version of course everything behaves, but on the 3.2.25 version the prompt that returns shows my cursor flashing in the middle:
Steps to repeat are:
Code:
1. login as user and receive the following prompt:
[28-09-2017 17:36:20][~]
[genomst][oracle@pwdchora51]$
2. Press ctrl+r and search for vim
[28-09-2017 17:36:20][~]
(reverse-i-search)`vim': vim .bashrc
3. Press left arrow key (could be any but this shows just how far I have moved back)
[28-09-2017 17:36:20][~]
[genomst][oracle@pwdchora51]$ vim .bashrc
^
^ indicates where cursor is on my screen
When looking at the setting of the prompt you will see a variable:
Code:
${!DB_COL}
If I remove this my cursor is under the last right hand square bracket (])
I did also find that if I replace $DB_USER with a string of text like:
Code:
[none]
This cause the same issue. Without the square brackets and a string of 4 characters or less the prompt works, but with more than 4 characters it behaves oddly as well.
Any light that someone could shed on this issue would be much appreciated
Please let me know if any further detail is required??
Hey, your bashrc is very fragmented, I've had to piece together the "pieces of PS1" on my own text editor.
Bash has problems coping with extraneous characters within the command prompt, or even with updating COLUMNS to the proper value, and if you want a festive PS1, you have to exercise caution.
Jeez, you have a *newline* in your PS1? I don't know, man. Give this one a shot and let me know how it works:
Code:
# Colours
RED=$'\033[1;31m'
GREEN=$'\033[1;32m'
YELLOW=$'\033[1;33m'
BLUE=$'\033[1;34m'
CYAN=$'\033[1;36m'
NORM=$'\033[0m'
# PS1 pieces
DATE='\D{%d-%m-%Y} \t'
DB_USER='none'
if [[ ${EUID} == 0 ]] ; then
PS1='\[${YELLOW}\]${DATE}\[${GREEN}\]\w\[${NORM}\]\n\[${BLUE}\]'
PS1+='${DB_USER}\[${RED}\]\u@\h\$ '
fi
Bash needs the escaped square brackets to know to account for unprintable characters when calculating line length, but I have absolutely no clue what it's going to do with a newline.
^ erm, that sounds confusing.
escaped square brackets:
Code:
\[ ..stuff.. \]
have to be used for anything that does not take up actual space, like changing attributes etc, otherwise one will see problems like you described.
this does NOT mean that you cannot have actual square brackets
Code:
[\u@\h]
in your PS1.
why this differs between bash versions, i cannot say.
oh, and mine also has a newline in it and has been bulletproof on bash 4.4.12:
Code:
if [[ ${EUID} == 0 ]] ; then
color=1 # red
else
color=2 # green
fi
if [ "$TERM" != "linux" ]; then
PS1="\[$(tput setaf $color)\]\[$(tput rev)\] \[$(tput sgr0)\]\[$(tput setaf 5)\]\${?#0}\[$(tput setaf $color)\] \u@\h \w\[$(tput sgr0)\]\n\[$(tput rev)\] \[$(tput sgr0)\] "
else
PS1="\[$(tput setaf $color)\]\[$(tput rev)\] \[$(tput sgr0)\]\[$(tput setaf 5)\]\${?#0}\[$(tput setaf $color)\] \t \u@\h \w\[$(tput sgr0)\]\n\[$(tput rev)\] \[$(tput sgr0)\] "
fi
unset color
After adding additional back slashes before all [ and ], when I log in I see the following:
Hold on... Like ondoho has pointed out, you need a square bracket escaped with only *one* backslash, before and after colors, and other unprintables. Two backslashes in series is actually interpreted as a single literal backslash, depending on context.
Add square brackets with no backslash if you want to display an actual square bracket.
I have simply fixed the obvious problem, as I saw it, but admittedly did not take the time to test my solution.
Try using your color sequences in the form I've used in my example: RED=$'\033[1;31m'. And enclose the entire PS1
with single quotes, rather than double quotes.
In other words, if you want to see "[hostname]", then you would write '[hostname]'.
If you want to see "hostname", in red, then you would write something like: '\[$RED\]hostname\[$NORM\]'.
I have used the $'\033[XXm' form, because as far as I understand, the prompt is evaluated each time it is drawn, therefore it is executing 8 calls to the external program "tput" unnecessarily. Whether this matters is up to you, of course. tput would add extra portability on systems which might have different sequences for colors. Then again, tput itself might not exist on those systems, as it is a part of ncurses, if I recall correctly.
That way you can also use single quotes to add additional solidity, as stray escape sequences can be unpredictable IME.
Single quotes won't work as then none of the variables get interpreted properly. Also, if you look at my colour settings, I already had [] around my colours.
So currently I am no closer to working out what 3.2.25 does not like
I have also tried the octal value \033 instead of \e but to no avail
That's simply a consideration of portability. If your shell recognizes \e, then you're set.
I personally either use the $'\033[1;31m' form, or I directly insert the escape character rather than using the $'\033'.
Like so:
$ echo <CTRL - V><Escape>[31mRed.
I haven't had a good experience with double quotes. That's why I've tried to move the expansion of your variables outside of the main PS1 string. The $RED inside the PS1 will be replaced with <Escape>[31m, even when it is enclosed in single quotes. But it will *not* replace \033 with <Escape> when inside single quotes. I don't think that makes a great deal of sense, but it is what it is.
Anyhow, good luck with what you're doing. It's no fun messing around with Bash settings.
Slight addendum Turns out that having $NORM at the end to reset does not perform the same as the tput command and when I search for longer items from history it again does not
finish at the correct spot and whilst it shows the whole line when I press the 'end' key it takes me to a point several (13) characters from the end.
So, for now, I have put the final tpu in and all seems to be working:
Again this shows the same strangeness in that if I use just 'none' it works ok, but once I add a few 'xxx' characters it gets lost trying to show where the cursor should be.
ummm ... only call tput sgr0 twice at the end of the prompt, and as indicated in post #10, that was how it came from that web page as the suggested prompt
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.