带有最后退出代码的Bash提示

时间:2013-05-23 13:23:15

标签: linux bash prompt

所以,我一直在尝试通过bash提示进行自定义,以便它看起来像

[feralin@localhost ~]$ _

有颜色。我设法得到恒定的颜色(每次看到提示时颜色相同)但我希望用户名('feralin')显示为红色,而不是绿色,如果最后一个命令具有非零退出状态。我提出了:

\e[1;33m[$(if [[ $? == 0  ]]; then echo "\e[0;31m"; else echo "\e[0;32m"; fi)\u\e[m@\e[1;34m\h \e[0;35m\W\e[1;33m]$ \e[m

然而,根据我的观察,当$(if ...; fi)运行时,.bashrc似乎被评估一次,并且结果在之后永远被替换。这使得名称始终为绿色,即使最后一个退出代码非零(如echo $?)。这是发生了什么?或者我的提示是否只是其他错误?很长的问题,如何提示我使用上一个退出代码?

8 个答案:

答案 0 :(得分:87)

当您开始在复杂的PS1上边界时,您可以考虑使用PROMPT_COMMAND 这样,您可以将其设置为一个函数,并在每个命令之后运行它以生成提示。

您可以在~/.bashrc

中尝试以下操作
PROMPT_COMMAND=__prompt_command # Func to gen PS1 after CMDs

__prompt_command() {
    local EXIT="$?"             # This needs to be first
    PS1=""

    local RCol='\[\e[0m\]'

    local Red='\[\e[0;31m\]'
    local Gre='\[\e[0;32m\]'
    local BYel='\[\e[1;33m\]'
    local BBlu='\[\e[1;34m\]'
    local Pur='\[\e[0;35m\]'

    if [ $EXIT != 0 ]; then
        PS1+="${Red}\u${RCol}"      # Add red if exit code non 0
    else
        PS1+="${Gre}\u${RCol}"
    fi

    PS1+="${RCol}@${BBlu}\h ${Pur}\W${BYel}$ ${RCol}"
}

这应该做你想要的声音。 如果您想查看我使用__prompt_command函数执行的所有操作,请查看我的bashrc sub file

答案 1 :(得分:14)

如果您不想使用提示命令,则需要考虑两件事:

  1. 获得$的价值?在其他任何事情之前,否则它将被覆盖
  2. 转出PS1中的所有$(因此在分配时不会对其进行评估)
  3. 使用变量的工作示例

    PS1="\$(VALU="\$?" ; echo \$VALU ; date ; if [ \$VALU == 0 ]; then echo zero; else echo nonzero; fi) " 
    

    没有变量的工作示例

    在任何覆盖$?的命令之前,if必须是第一件事。

    PS1="\$(if [ \$? == 0 ]; then echo zero; else echo nonzero; fi) "
    

    注意\$()是如何转义的,因此不会立即执行,但每次使用PS1时都会执行。还\$?

    的所有用途

答案 2 :(得分:4)

我想保留默认的Debian颜色,打印确切的代码,并且只在失败时打印它:

it 'returns authorization error message' do
  get :index, format: :json
  ...
end

答案 3 :(得分:1)

紧凑的解决方案:

PS1='... $(code=${?##0};echo ${code:+[error: ${code}]})'

此方法不需要PROMPT_COMMAND(显然这有时会变慢),并且如果退出代码为非零,则打印[error: <code>],如果退出代码为零,则不输出:

... > false
... [error: 1]> true
... >

根据您的喜好更改[error: ${code}]部分,其中${code}是要打印的非零代码。

请注意,使用'可以确保在以后评估PS1而不是启动Shell时执行内联$() shell。

作为奖励,您可以通过在重置之前添加\e[01;31m并在其后添加\e[00m使它变为红色,成为红色。

PS1='... \e[01;31m$(code=${?##0};echo ${code:+[error: ${code}]})\e[00m'

-

工作原理:

  • 它使用bash parameter substitution
  • 首先,${?##0}将读取上一条命令的退出代码$?
  • ##将从一开始就删除任何0模式,从而有效地使0结果为空var(感谢@blaskovicz的诀窍)
  • 我们需要将其分配给临时code变量,因为我们需要进行另一次替换,并且不能嵌套
  • 只有设置了变量${code:+REPLACEMENT}(非空),REPLACEMENT才会打印code部分
  • 这样,我们可以在其周围添加一些文本和方括号,然后再次内联引用该变量:[error: ${code}]

答案 4 :(得分:0)

改进了@demure

我认为这很重要,因为并不总是退出状态为0或1。

if [ $EXIT != 0 ]; then
    PS1+="${Red}${EXIT}:\u${RCol}"      # Add red if exit code != 0
else
    PS1+="${Gre}${EXIT}:\u${RCol}"      # Also displays exit status
fi

答案 5 :(得分:0)

要保留原始提示格式(不仅是颜色),可以在~/.bashrc的末尾附加以下内容:

PS1_ORIG=$PS1 # original primary prompt value
PROMPT_COMMAND=__update_prompt # Func to be re-evaluated after each command is executed
__update_prompt() {
    local PREVIOUS_EXIT_CODE="$?"
    if [ $PREVIOUS_EXIT_CODE != 0 ]; then
        local RedCol='\[\e[0;31m\]'
        local ResetCol='\[\e[0m\]'
        local replacement="${RedCol}\u${ResetCol}"

        # Replace username color
        PS1=${PS1_ORIG//]\\u/]$replacement}
        ## Alternative: keep same colors, append exit code
        #PS1="$PS1_ORIG[${RedCol}error=$PREVIOUS_EXIT_CODE${ResetCol}]$ "
    else
        PS1=$PS1_ORIG
    fi
}

另请参阅有关保留用户名颜色并仅将红色错误代码附加到原始提示格式末尾的替代方法的评论

答案 6 :(得分:0)

为什么我自己没有考虑这个问题?)我发现这很有趣,并将此功能添加到我的'info-bar'项目中。如果上一条命令失败,眼睛将变成红色。

#!/bin/bash
eyes=(O o ∘ ◦ ⍤ ⍥) en=${#eyes[@]} mouth='_'                                                           
face () { # gen random face                                                                           
    [[ $error -gt 0 ]] && ecolor=$RED || ecolor=$YLW                                                  
    if [[ $1 ]]; then printf "${eyes[$[RANDOM%en]]}$mouth${eyes[$[RANDOM%en]]}"                       
                 else printf "$ecolor${eyes[$[RANDOM%en]]}$YLW$mouth$ecolor${eyes[$[RANDOM%en]]}$DEF"  
    fi                                                                                                
}                                                                                                     
info () { error=$?                                                                                    
    [[ -d .git ]] && {  # If in git project folder add git status to info bar output                  
        git_clr=('GIT' $(git -c color.ui=always status -sb)) # Colored output 4 info                  
        git_tst=('GIT' $(git                    status -sb)) # Simple  output 4 test                  
    }                                                                                                 
    printf -v line "%${COLUMNS}s"                            # Set border length                      
    date=$(printf "%(%a %d %b %T)T")                         # Date & time 4 test                     
    test=" O_o $PWD  ${git_tst[*]} $date o_O "               # Test string                            
    step=$[$COLUMNS-${#test}]; [[ $step -lt 0 ]] && step=0   # Count spaces                           
    line="$GRN${line// /-}$DEF\n"                            # Create lines                           
    home="$BLD$BLU$PWD$DEF"                                  # Home dir info                          
    date="$DIM$date$DEF"                                     # Colored date & time                    
           #------+-----+-------+--------+-------------+-----+-------+--------+                       
           # Line | O_o |homedir| Spaces | Git  status | Date|  o_O  |  Line  |                       
           #------+-----+-------+--------+-------------+-----+-------+--------+                       
    printf "$line $(face) $home %${step}s ${git_clr[*]} $date $(face) \n$line" # Final info string    
}                                                                                                     
PS1='${debian_chroot:+($debian_chroot)}\n$(info)\n$ '                                                 
case "$TERM" in xterm*|rxvt*)                                                                         
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)} $(face 1) \w\a\]$PS1";;                            
esac 

enter image description here

答案 7 :(得分:0)

以下在退出代码为零时提供一个领先的绿色复选标记,在所有其他情况下提供一个红色叉号。其余部分是标准的彩色提示。可以修改 printf 语句以呈现最初请求的两种状态。

PS1='$(if [ $? -eq 0 ]; then printf "\033[01;32m""\xE2\x9C\x93"; else printf "\033[01;31m""\xE2\ x9C\x95"; fi) [\e[00;32m]\u@\h[\e[00;30m]:[\e[01;33m]\w[\e[01;37m]$ '< /p>