GREEN="\e[1;32m"
RED="\e[1;31m"
NONE="\e[m"
get_exit_status(){
es=$?
if [ $es -eq 0 ]
then
echo -e "${GREEN}${es}${NONE}"
else
echo -e "${RED}${es}${NONE}"
fi
}
get_path(){
#dummy function
echo "PATH"
}
PROMPT_COMMAND='exitStatus=$(get_exit_status)'
以下给出了正确的 exitStatus 但颜色变量未扩展:
PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
然而,下面的给了我颜色,但退出状态没有更新:
PS1="${RED}\h $(get_path) ${exitStatus}${NONE} "
这样做的正确方法是什么?我该如何解决这个问题,以便 exitStatus 和颜色都起作用?
答案1
吉尔斯指出了你的主要问题,但我想尝试以不同的方式解释它。
Bash 解释了特殊提示转义仅有的前展开提示中的任何变量。这意味着\e
在从提示符扩展的变量中使用不起作用,即使它可以直接在PS1
.
例如,这按预期工作,并给出红色文本:
PS1='\e[1;31m this is in red '
但这不是,它只是\e
在提示中添加了一个文字:
RED='\e[1;31m'
PS1="$RED not in red "
如果要将颜色转义存储在变量中,可以使用 ANSI-C 引号 ( $'...'
) 将文字转义字符放在变量中。
为此,您可以更改GREEN
、RED
和的定义NONE
,因此它们的值是实际的转义序列。
GREEN=$'\033[1;32m'
RED=$'\033[1;31m'
NONE=$'\033[m'
如果你这样做,你的第PS1
一个单引号应该可以工作:
PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
然而,这样你就会遇到第二个问题。
尝试运行它,然后按Up Arrow,然后按Home,光标将不会返回到行的开头。
要解决此问题,请更改PS1
为包含\[
并\]
围绕颜色转义序列,例如
PS1='\[${RED}\]\h $(get_path) $?\[${NONE}\] '
您不能get_exit_status
在这里正确使用,因为它的输出包含打印(退出代码)和非打印字符(颜色代码),并且无法在提示中正确标记它。放置\[...\]
会将其标记为未完整打印,这是不正确的。您必须更改该函数,以便它只打印正确的颜色代码,然后\[...\]
在提示中将其括起来。
答案2
当您运行时PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
,PS1
变量设置为${RED}\h $(get_path) ${exitStatus}${NONE}
,其中仅\h
是提示转义序列。后提示序列被扩展(产生${RED}darkstar $(get_path) ${exitStatus}${NONE}
),shell 执行通常的扩展,例如变量扩展。您会看到一个类似于 的显示提示\e[1;31mdarkstar PATH 0\e[m
。一路上没有任何东西将\e
序列扩展为实际的转义字符。
当您运行时PS1="${RED}\h $(get_path) ${exitStatus}${NONE} "
,该PS1
变量被设置为\e[1;31m\h PATH 0\e[m
。变量RED
、exitStatus
和NONE
在赋值时展开。然后提示包含三个提示转义序列(\e
、\h
、 和\e
再次)。此阶段没有可扩展的 shell 变量。
为了查看颜色,您需要颜色变量包含实际的转义字符。你可以这样做:
RED=$'\033[1;31m'
NONE=$'\033[m'
PS1='\[${RED}\]\h \w $?\[${NONE}\] '
$'…'
扩展反斜杠八进制序列和一些反斜杠字母序列,例如\n
,但不包括\e
。我对您的提示做了另外三处更改:
- 使用
\[…\]
非打印序列,例如颜色更改命令。否则你的显示最终会出现乱码,因为 bash 无法计算出提示符的宽度。 \w
是一个内置的转义序列,用于打印当前目录。- 如果您一开始
$?
就没有 ,则不需要在提示中显示任何复杂的内容。PROMPT_COMMAND
答案3
尝试:
PS1='`exitStatus=$?;if [ $exitStatus -eq 0 ];then echo "\['${GREEN}'\]";else echo "\['${RED}'\]";fi;echo "\h $(get_path) ${exitStatus}${NONE}"`'
答案4
干得好- 这对 Ubuntu 和其他 Linux(Linuxen?)中的我(TM)有效。
放入退出代码检测的原因$PS1
是一台主机在读取 .bashrc 之前设置了只读$PROMPT_COMMAND
。