PS1中的命令替换在应该更新的时候不会更新;缓存的输出?

时间:2019-03-19 07:24:58

标签: bash

我正在尝试在终端的提示符下添加分支名称,例如user@host:directory [branch]。我尝试了两个代码,发现Code.2无法正常工作。签出另一个分支时不反映分支名称。看来bash正在缓存上一​​个命令的结果。

有人可以告诉我Code.2的问题是什么吗?我还想知道\之前的$()是什么意思?

环境

  • macOS 10.14.3
  • git 2.19.2

Code.1-有效

user@host:directory [master]$ cat ~/.bashrc
PS1="\u@\h:\W \$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/[\1]/')\$ "
user@host:directory [master]$ git checkout another-branch
user@host:directory [another-branch]$ 
user@host:directory [another-branch]$ git checkout master
user@host:directory [master]$ 

代码2-失败

user@host:directory [master]$ cat ~/.bashrc
BRANCH_NAME=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/[\1]/')
PS1="\u@\h:\W ${BRANCH_NAME}\$ "
user@host:directory [master]$ git checkout another-branch
user@host:directory [master]$ 
user@host:directory [master]$ git checkout master
user@host:directory [master]$ 

1 个答案:

答案 0 :(得分:2)

这确实与Git无关-纯粹是在bash本身中执行所需操作的问题。

Bash有五个名为described in the documentation的变量,分别名为PS0PS1PS2PS3PS4

  

PS0       该参数的值像PS1一样展开,并在读取命令之后和执行命令之前由交互式shell显示。

     

PS1   主提示字符串。默认值为‘\s-\v\$ ’。有关在显示PS1之前展开的转义序列的完整列表,请参见Controlling the Prompt

     

PS2   次要提示字符串。默认值为‘> ’。在显示之前,PS2的扩展方式与PS1相同。

     

PS3   该变量的值用作select命令的提示。如果未设置此变量,则选择命令将以‘#? ’

提示      

PS4   设置PS1后,此参数的值将像-x一样展开,并且展开的值是在回显命令行之前打印的提示(请参见The Set Builtin)。必要时,将扩展值的第一个字符复制多次,以指示多个间接级别。默认值为‘+ ’

这里最棘手的部分是PS1在通过扩展提示进行评估之前,会通过扩展进行评估。此评估具有许多不可思议的转义序列,所有这些都在linked section about controlling the prompt中进行了描述。然后,如文档所述:

  

对字符串进行解码后,可以根据参数promptvars shell选项的值(请参阅The Shopt Builtin)通过参数扩展,命令替换,算术扩展和引号删除来扩展它。

命令替换部分在有效的设置(第一个.bashrc,您称为Code.1)中很重要。该bashrc部分读取:

PS1="\u@\h:\W \$(git branch)\$ "

(为了简化说明,我将其缩短了很多内容)。当bash来源此bashrc时,将对这一行进行一次评估,因此,双引号内的每个元素此时都必须进行参数扩展,命令替换,算术扩展和引号删除 。所有这些的结果是将PS1设置为:

\u@\h:\W $(git branch)$ 

(上面一行的末尾有一个空格)。

现在bash每次要打印提示时,都会再次评估PS1 。此 second (但重复进行)评估对\u\H\W进行解码,使shell保留:

user@host:directory $(git branch) $ 

此序列现在进行

  

参数扩展,命令替换,算术扩展和引号删除

再次

这次$(git branch)产生命令替换结果。 (这将显示为masteranother-branch,不带方括号;我放下的sed会解决这些问题。)

bashrc的“ Code.2”版本部分读取:

PS1="\u@\h:\W ${BRANCH_NAME}\$ "

在读取该bashrc本身时会经历一次常规规则,而留下来:

\u@\h:\W [master]$ 

(再次在末尾有一个空格)作为存储在PS1中的值。在读取每个命令之前,将再次对该值进行“解码[并]扩展”,但是这次没有命令可作为命令替换的一部分运行。文字[master]嵌入值中。