LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-28-2017, 03:21 AM   #1
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
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??
 
Old 09-28-2017, 01:05 PM   #2
Fat_Elvis
Member
 
Registered: Oct 2016
Distribution: FreeDOS 1.2
Posts: 309

Rep: Reputation: 92
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.
 
Old 09-28-2017, 01:09 PM   #3
Fat_Elvis
Member
 
Registered: Oct 2016
Distribution: FreeDOS 1.2
Posts: 309

Rep: Reputation: 92
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.

Last edited by Fat_Elvis; 09-28-2017 at 01:18 PM.
 
Old 09-28-2017, 08:56 PM   #4
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Original Poster
Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
After adding additional back slashes before all [ and ], when I log in I see the following:
Code:
29-09-2017 11:24:58~
genomstoracle@pwdchora51$
As you can see that removes all the square brackets.

Then when I press ctrl+r I see:
Code:
29-09-2017 11:24:58~
(reverse-i-search)`':enomstoracle@pwdchora51$
So I am going to go with the fact that escaping the square brackets is not the answer.

You may have also missed the part where I said that under 4.1.2 the prompt works correctly with zero issues
 
Old 09-29-2017, 08:33 AM   #5
ondoho
LQ Addict
 
Registered: Dec 2013
Posts: 19,872
Blog Entries: 12

Rep: Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053
^ 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
 
Old 09-29-2017, 11:19 AM   #6
Fat_Elvis
Member
 
Registered: Oct 2016
Distribution: FreeDOS 1.2
Posts: 309

Rep: Reputation: 92
Quote:
Originally Posted by grail View Post
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\]'.

Quote:
Originally Posted by ondoho View Post
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)\] "
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.

Last edited by Fat_Elvis; 09-29-2017 at 11:40 AM.
 
Old 09-30-2017, 12:03 PM   #7
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Original Poster
Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
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
 
Old 09-30-2017, 01:21 PM   #8
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Original Poster
Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
As a side test, I have implemented the following in 3.2.25 environment:
Code:
PS1='\[\e[1;33m\][\D{%d-%m-%Y} \t]\[\e[1;32m\][\w]\n\[\e[1;34m\]nonex\[\e[m\][\u@\h]\$ '
This also does not work but I feel it at least rules out the use of variables being used in the prompt as a cause.

Again, simply removing the 'x' from 'nonex' causes everything to work ok??

I have also tried the octal value \033 instead of \e but to no avail
 
Old 09-30-2017, 02:00 PM   #9
Fat_Elvis
Member
 
Registered: Oct 2016
Distribution: FreeDOS 1.2
Posts: 309

Rep: Reputation: 92
Quote:
Originally Posted by grail View Post
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.

Last edited by Fat_Elvis; 09-30-2017 at 02:07 PM.
 
Old 10-01-2017, 08:47 PM   #10
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Original Poster
Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
So, I stumbled across the following page which helped me identify that I needed a closing reset of colour to help remove issues.

The suggested prompt from above link, which also works:
Code:
export PS1="\[$(tput bold)\]\[$(tput setaf 3)\][\D{%d-%m-%Y} \t]\[$(tput bold)\]\[$(tput setaf 2)\][\w]\n\[$(tput bold)\]\[$(tput setaf 4)\][none]\[$(tput sgr0)\][\u@\h]\\$ \[$(tput sgr0)\]"
As you can see there is an additional tput sgr0 at the end. So I replicated in my own format with:
Code:
PS1="$YELLOW$DATE$GREEN$LPATH\n${!DB_COL}$DB_USER$UCOL$WHERE\\$ $NORM"
And, viola, no more weed miscalculation of where the prompt should be.

And I can confirm it works just fine in higher bash version as well
 
Old 10-01-2017, 09:43 PM   #11
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Original Poster
Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
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:
Code:
PS1="$YELLOW$DATE$GREEN$LPATH\n${!DB_COL}$DB_USER$UCOL$WHERE\\$ \[$(tput sgr0)\]
 
Old 10-02-2017, 01:10 AM   #12
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Original Poster
Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Seems I have jumped the gun altogether

Once I found a long enough line in history, even the all tput option no longer works.
The following was the last tested prompt:
Code:
PS1="\[$(tput bold)\]\[$(tput setaf 3)\][\D{%d-%m-%Y} \t]\[$(tput bold)\]\[$(tput setaf 2)\][\w]\n\[$(tput bold)\]\[$(tput setaf 4)\]nonexxxxx\[$(tput sgr0)\][\u@\h]\\$ \[$(tput sgr0)\]"
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.

Back to the drawing board
 
Old 10-02-2017, 02:04 AM   #13
Fat_Elvis
Member
 
Registered: Oct 2016
Distribution: FreeDOS 1.2
Posts: 309

Rep: Reputation: 92
Wow... I didn't even notice you didn't put [0m at the end.

tput sgr0 simply outputs this: $'\033(B\033[m', which you can use instead of calling that command eight times, if you like.

Try it:
$ hexdump -C <<< "$(tput sgr0)"
 
Old 10-02-2017, 02:14 AM   #14
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Original Poster
Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
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
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
PS1 bash prompt with new line and color wolfv Linux - Newbie 9 02-19-2017 06:38 AM
PS1 prompt way to long paul_e_t Linux - Newbie 9 08-16-2014 10:28 AM
[SOLVED] what are the other differences between fedora versions except their kernel versions teja_vijjapu Fedora 1 01-23-2012 06:38 AM
Post your BASH prompt [PS1]? introuble General 11 12-27-2006 03:47 PM
$PS1 different in X and prompt codec Slackware 7 06-27-2004 04:42 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:37 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration