在bash PS1中设置变量

在bash PS1中设置变量,bash,ps1,Bash,Ps1,我试图自定义我的bash提示符,但在一些条件方面遇到了问题 我当前的PS1如下所示 export PS1="\ $PS1USERCOLOR\u\ $COLOR_WHITE@\ $COLOR_GREEN\h\ $COLOR_WHITE:\ $COLOR_YELLOW\W\ \`if type parse_git_branch > /dev/null 2>&1; then parse_git_branch; fi\`\ \`if [ \$? = 0 ]; then echo -e

我试图自定义我的bash提示符,但在一些条件方面遇到了问题

我当前的
PS1
如下所示

export PS1="\
$PS1USERCOLOR\u\
$COLOR_WHITE@\
$COLOR_GREEN\h\
$COLOR_WHITE:\
$COLOR_YELLOW\W\
\`if type parse_git_branch > /dev/null 2>&1; then parse_git_branch; fi\`\
\`if [ \$? = 0 ]; then echo -e '$COLOR_WHITE'; else echo -e '$COLOR_RED'; fi\`\$\     
$COLOR_WHITE"
  • 前6行只是设置了常规的
    PS1
    stuff

  • 第7行调用一个函数来显示当前git分支和状态(如果适用)

  • 第8行然后测试上一个命令的返回代码,并更改末尾的
    $
    的颜色

  • 第9行将提示符设置回白色,以便用户发出命令

但是,第8行响应的是第7行函数的返回代码,而不是我最初预期的前一个命令

我试着把8号线移到7号线之前,一切都正常。但是我不希望第8行在第7行之前,因为
$
必须在末尾

我在前面尝试过将一个变量设置为
$?
的值,然后像这样测试该变量

export PS1="\
\`RETURN=\$?\`\
$PS1USERCOLOR\u\
$COLOR_WHITE@\
$COLOR_GREEN\h\
$COLOR_WHITE:\
$COLOR_YELLOW\W\
\`if type parse_git_branch > /dev/null 2>&1; then parse_git_branch; fi\`\
\`if [ \$RETURN = 0 ]; then echo -e '$COLOR_WHITE'; else echo -e '$COLOR_RED'; fi\`\$\     
$COLOR_WHITE"
但这不起作用

有人知道如何解决我的问题吗?

解决了

我需要使用
PROMPT\u命令
变量来设置
RETURN
变量
PROMPT_命令
是在加载
PS1
之前调用的命令

我的脚本现在看起来像

PROMPT_COMMAND='RETURN=$?'

export PS1="\
$PS1USERCOLOR\u\
$COLOR_WHITE@\
$COLOR_GREEN\h\
$COLOR_WHITE:\
$COLOR_YELLOW\W\
\`if type parse_git_branch > /dev/null 2>&1; then parse_git_branch; fi\`\
\`if [[ \$RETURN = 0 ]]; then echo -e '$COLOR_WHITE'; else echo -e '$COLOR_RED'; fi\`\$\     
$COLOR_WHITE"

此问题的标准解决方案是使用
bash
环境变量
PROMPT\u命令
。如果将此变量设置为shell函数的名称,则在显示每个
bash
提示之前,将执行所述函数。然后,在这个函数中,你可以设置你想要的任何变量。下面是我在my
.bashrc
中几乎完全按照您的要求所做的:

titlebar_str='\[\e]0;\u@\h: \w\a\]'
time_str='\[\e[0;36m\]\t'
host_str='\[\e[1;32m\]\h'
cwd_str='\[\e[0;33m\]$MYDIR'
git_str='\[\e[1;37m\]`/usr/bin/git branch --no-color 2> /dev/null | /bin/grep -m 1 ^\* | /bin/sed -e "s/\* \(.*\)/ [\1]/"`\[\e[0m\]'
dolr_str='\[\e[0;`[ $lastStatus -eq 0 ] && echo 32 || echo 31`m\]\$ \[\e[0m\]'
export PS1="$titlebar_str$time_str $host_str $cwd_str$git_str$dolr_str"

function prompt_func {
    # Capture the exit status currently in existence so we don't overwrite it with
    # any operations performed here.
    lastStatus=$?

    # ... run some other commands (which will have their own return codes) to set MYDIR
}

export PROMPT_COMMAND=prompt_func

现在,bash将在显示每个新提示之前运行
prompt\u func
。前面命令的退出状态在
lastStatus
中捕获。由于
git_str
dolr_str
等都是用单引号定义的,因此当bash取消引用
PS1
时,变量(包括
lastStatus
)和其中的命令将被重新评估。正确的方法是使用
PROMPT_命令
,如下所示:

prompt_cmd () {
    LAST_STATUS=$?
    PS1="$PS1USERCOLOR\u"
    PS1+="$COLOR_WHITE@"
    PS1+="$COLOR_GREEN\h"
    PS1+="$COLOR_WHITE:"
    PS1+="$COLOR_YELLOW\W"
    if type parse_git_branch > /dev/null 2>&1; then
        PS1+=$(parse_git_branch)
    fi
    if [[ $LAST_STATUS = 0 ]]; then
        PS1+="$COLOR_WHITE"
    else
        PS1+="$COLOR_RED"
    fi
    PS1+='\$'
    PS1+="$COLOR_WHITE"
}
由于
PROMPT\u命令
是在每次提示之前计算的,因此您只需执行为每个提示实例设置
PS1
的代码,而不是尝试在字符串本身中嵌入延迟逻辑

几点注意:

  • 在覆盖所需的值之前,必须在代码的第一行中保存
    $?
  • 除了
    \$
    ,我对大多数步骤使用双引号;如果愿意,您可以使用
    PS1+=“\\\$”

  • 我将所有if语句拆分成一个单独的函数或脚本,并进行独立测试。在子shell中设置变量时返回颜色。这不会传递到另一个子壳或父壳。这很有意义!你知道如何正确地做这件事吗?不要在两个测试中使用两个子外壳。使用一个,在子shell的开头设置
    RETURN
    ,然后在结尾使用它。请参阅,您还可以在
    PROMPT\u命令中执行完整的if测试,并使用字符串设置变量以在
    PS1
    中使用。使用
    PROMPT\u命令
    ,通常只需有条件地设置,
    dolr\u str
    在函数内部,而不是尝试在
    dolr\u str
    的值中嵌入命令。以上是在许多不同心态下进行多次编辑的结果。:)那太棒了,而且更优雅。虽然我在
    $
    之后添加了一个空格,但我使用它的方式与此完全相同。