使用变量存储PS1的终端颜色代码?


33

在我的文章中.bashrc,我使用ANSI终端颜色代码对各个位进行着色。看起来像这样:

PS1='\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ '

其中virtual_envgit_branch是在stdout上输出内容的bash函数。

现在,为了使其更易于阅读和修改,我想将颜色代码存储在变量中并对其进行引用,而不是将它们直接嵌入PS1。所以我有一堆这样的变量:

GREEN="\[\033[32m\]"
YELLOW="\[\033[33m\]"
RESET="\[\033[0m\]"

我希望能够编写如下内容:

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

但这是行不通的-提示中会显示颜色代码,就像逃脱了一样。如果我使用双引号代替PS1,则颜色可以正常工作,但是提示仅在我这样做时才会更改source ~/.bashrc

我已经试过我见过的人做其他事情-使用printf,使用单引号的颜色,把\[\]PS1,而不是颜色可变的,但似乎没有任何工作。

如何将变量用于颜色代码?


你能给我们你的.bashrc吗?
cuonglm

@cuonglm您所有的.bashrc都属于我们吗?我将展示自己。
CivFan

Answers:


20

解决方案是让外壳在定义提示时替换颜色变量,而不是函数。为此,请使用您最初尝试使用的双引号,但是请转义命令,以便在绘制提示之前不对其进行求值。

PS1="\u@\h:\w${YELLOW}\$(virtual_env)${GREEN}\$(git_branch)${RESET}$ "

注意\之前的$()每个命令。

如果我们对此表示赞同,则会看到:

echo "$PS1"
\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ 

如您所见,颜色变量被替换,但命令未被替换。


1
如果$(git_branch)也试图使用$ {YELLOW}等进行打印,这似乎不起作用。仅在该部分,您仍将获得所有[]字符。
世界银行里德

7

问题是您的变量GREEN包含由“反斜杠括号反斜杠零三三”组成的文字字符串,依此类推。例如,它不包含使终端改变颜色所需的ASCII转义字符。

您可以手动将控制字符放入GREEN(和YELLOWRESET),但是更好的选择是首先使用tput,这样您就无需硬编码任何内容,并且将支持任何终端类型。

GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
RESET="$(tput setaf 0)"

直接将“反斜杠零三三”等放到世界中的原因PS1是,某些反斜杠序列的解释是bash提示的功能(请参阅手册中的PROMPTING部分。此替换发生参数扩展,命令之前但是,替换,算术扩展和引号删除也不适用于所有其他操作的结果。


5
以这种方式进行操作时,您需要将颜色变量包装\[\]在中$PS1。例如:PS1='\u@\h:\w\[${YELLOW}\]'。如果您不这样做,那么最终会得到一条长命令,该命令将自动换行到下一行,那么您将遇到各种问题。Shell使用\[\]来确定哪些字符不可打印,因此不会在提示长度的计算中考虑它们。它需要它,以便当它超过端子宽度时可以正确地画线。
帕特里克

我不知道tput,谢谢。我现在将使用帕特里克(Patrick)的答案,但是如果有机会,我将重新讨论。
Ismail Badawi 2014年

2

更改填充$ GREEN,$ YELLOW和$ RESET的方式:

GREEN="$(echo -e "\033[32m")"
YELLOW="$(echo -e "\033[33m")"
RESET="$(echo -e "\033[0m")"

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

1
实际上,这与Celada的回答完全相同。但是,如果终端使用不同的转义码进行颜色设置,则Celada的便携性更高。多行提示也将出现相同的问题。
Patrick

2
\[…\]位需要保留在提示中,您不能将其填充到变量中。您已将其完全删除,这将导致显示问题(光标不在bash期望的位置)。
吉尔斯(Gilles)'所以

除了@Patrick的问题之外,echo -e不可移植。
helpermethod 2014年

1
不可移植性带来更多功能- tput setaf不允许您从“浅”颜色集中进行选择,例如浅青色。@Cyrus的答案可以。
CivFan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.