我的PS1
在我的~/.bash_profile
:
export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]`__git_ps1`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "
(抱歉,我的颜色代码没有任何别名,我使用在线编辑器创建了此提示)
但如果我切换,当前显示的分支总是错误的
我不知道为什么会发生这种情况。如果我单独运行该命令,我会得到正确的值。
$ echo `__git_ps1`
(dev)
如果我获取 .bash_profile,新值将会出现(但下次切换时会出错)。难道我做错了什么?
答案1
export PS1="…`__git_ps1`…"
使用`__git_ps1`
内部双引号,此命令运行命令__git_ps1
并将其输出(和其他周围文本)分配给变量PS1
。因此,您的提示显示的是.bash_profile
执行时确定的分支。
__git_ps1
每次 bash 显示提示时都需要运行。 (实际上,在 git 信息发生更改之前,您不需要再次运行它,但这很难检测到。)有两种方法可以做到这一点。
`__git_ps1`
在变量中包含文字文本PS1
。确保 bash 配置为对提示字符串执行 shell 扩展,使用promptvars
选项打开;默认情况下就是这种情况,但可以使用 关闭它shopt -u promptvars
。PS1='\n\[…\]$(__git_ps1)\[…\]\$ '
通过从以下位置运行命令来更新提示内容
PROMPT_COMMAND
多变的。update_PS1 () { PS1="\\n\\[…\\]$(__git_ps1)\[…\]\\$ " } shopt -u promptvars PROMPT_COMMAND=update_PS1
顺便说一句,提示符是 shell 配置,而不是全局设置,所以你应该将其设置为~/.bashrc
,而不是~/.bash_profile
。
答案2
这只是一个简单的引用问题。如果必须使用反引号,请将其更改`__git_ps1`
为,或者: 。\$(__git_ps1)
\`__git_ps1\`
为了说服自己,只需将 PS1 更改为(如果您想完全恢复到之前的设置,请打开一个新的 shell 实例):
$ PS1="$(date) >"
Thu Nov 26 20:02:34 EST 2015 >_
唯一的问题是它会不是更新(等待几秒钟按 Enter 键)。
但这会:
$ PS1="\$(date) >"
Thu Nov 26 20:06:20 EST 2015
Thu Nov 26 20:06:25 EST 2015
就这样。写exit
。 (更新您的提示)回去工作。
答案3
http://mediadoneright.com/content/ultimate-git-ps1-bash-prompt
注意底部他们没有设置:
导出 PS1="\n... `__git_ps1 ...
将其设置为这个恶心的作品:
export PS1=$IBlack$Time12h$Color_Off'$(git branch &>/dev/null;\
if [ $? -eq 0 ]; then \
echo "$(echo `git status` | grep "nothing to commit" > /dev/null 2>&1; \
if [ "$?" -eq "0" ]; then \
# @4 - Clean repository - nothing to commit
echo "'$Green'"$(__git_ps1 " (%s)"); \
else \
# @5 - Changes to working tree
echo "'$IRed'"$(__git_ps1 " {%s}"); \
fi) '$BYellow$PathShort$Color_Off'\$ "; \
else \
# @2 - Prompt when not in GIT repo
echo " '$Yellow$PathShort$Color_Off'\$ "; \
fi)'
其相关位是“$(__git_ps1”(%s)”或“$(__git_ps1”{%s}”
答案4
我觉得现有的答案没有准确/清楚地传达根本原因。尽管它们可能会导致找到解决方案,但我不确定它们是否能教会观众应该吸取的教训。这个答案主要是从帮助观众达成理解的角度来回答。
快速回答
我在写完原始回复后想到了这种方法,因此将详细回复留在下面,但这是快速答案。
您的PS1
值将存储为替换版本,因为输入期间未使用转义。您可以像这样验证它:
原来的:
chadb@Chad-2in1 ~/code/videospeed-refactoring (master) 21:12:45
$ export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]`__git_ps1`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "
chadb@Chad-2in1 ~/code/videospeed-refactoring (master) 21:13:03
$ env |grep PS1
PS1=\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\] (master)\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\$
逃脱
chadb@Chad-2in1 ~/code/videospeed-refactoring (master) 21:19:42
$ export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]\`__git_ps1\`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "
chadb@Chad-2in1 ~/code/videospeed-refactoring (master) 21:20:02
$ env |grep PS1
PS1=\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]`__git_ps1`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\$
如您所见,__git_ps1
在第二个版本中保留了下来,而在第一个版本中,它显示了输入时 __get_ps1 的值。
继续我原来的答案。
解释
问题是,当 shell 执行命令时,它会在插入之前执行替换,因此会插入替换值而不是原始命令。
为了解决这个问题,您只需\
在存储之前使用转义字符来防止替换。这会导致命令的未转义可执行版本存储在内存中,以便 bash 会根据每个输入的命令重新评估它。
未转义的命令导致它在存储在内存中之前被执行和替换,这反过来又导致它仅在~/.bash_profile
第一次执行/获取时显示命令。
解决方案
原始命令
export export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]`__git_ps1`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "
$PS1 的原始存储值
包括字符串文字“ (master) ”
\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\] (master) \[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$
重要提示:为了避免混淆,该存储值仅代表对
__git_ps1
固定命令
export export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]\`__git_ps1\`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "
$PS1 的固定存储值
这次命令保持不变,以便在下次执行时将其替换。
"\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]`__git_ps1`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "
反引号不相关 - 证明
正如其他答案所提到的,您可以使用 $() 提供反引号,但是,这与此问题的根本原因无关。这些问题不应混为一谈。
老了[不是问题]
`__git_ps1`
新[不是问题]
$(__git_ps1)
原始命令没有反引号,未转义[不是问题,同样有问题]
export export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]$(__git_ps1)\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "
不带反引号的原始命令转义[以相同方式修复,带转义]
export export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]\$(__git_ps1)\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "
简化证明
为了简化这一点,让我们通过创建自定义 shell 命令来删除许多变量,该命令执行与 bash 类似的操作,只需使用文件sub_demo
作为存储介质将当前工作目录回显到控制台以显示中间状态。
未转义的 $PWD [问题]
[07:18 PM] ~/code $ echo $PWD
/c/Users/chadb/code
[07:36 PM] ~/code $ echo $PWD > sub_demo
[07:36 PM] ~/code $ cat sub_demo
/c/Users/chadb/code
请注意, 的替换值$PWD
已存储在文件中,从而破坏了用于检索该目录的命令的信息。如果我们只是从现在开始读出 sub_demo 的内容,它总是会产生相同的渲染值/c/Users/chadb/code
这样做很愚蠢,但为了说明目的,我将从多个位置读取文件的内容,以证明这实际上不会更改存储在其中的信息。
[08:01 PM] ~/code $ cat ~/code/sub_demo
/c/Users/chadb/code
[08:01 PM] ~ $ cat ~/code/sub_demo
/c/Users/chadb/code
[08:01 PM] ~/code/sub_demo_folder $ cat ~/code/sub_demo
/c/Users/chadb/code
请注意,无论文件夹如何,该值都不会更改。的内容~/code/sub_demo
从现在开始/c/Users/chadb/code
直到我们更改为止。
逃脱 $PWD [解决方案]
现在考虑是否$
通过转义字符\$
。
[08:06 PM] ~/code $ echo \$PWD > sub_demo
[08:06 PM] ~/code $ cat sub_demo
$PWD
正如您所看到的,该值现在存储为命令 - 与查找工作目录所需的命令相同。这有什么用?好吧,bash 会执行 $PS1 存储的值。让我们通过在开头添加 echo 来将文件的内容转换为可执行文件来模拟这一点。
为了完整性和对比,我将展示未转义和转义的版本。
[未逃脱]
[08:06 PM] ~/code $ echo "echo $PWD" > sub_demo
[08:11 PM] ~/code $ cat sub_demo
echo /c/Users/chadb/code
[逃脱]
[08:11 PM] ~/code $ echo "echo \$PWD" > sub_demo
[08:13 PM] ~/code $ cat sub_demo
echo $PWD
这还没有那么令人兴奋,但当你执行输出时真正的魔法就会发生。
最终简化证明
未转义 - 不起作用
[08:15 PM] ~/code $ echo "echo $PWD" > sub_demo
[08:15 PM] ~/code $ cat sub_demo
echo /c/Users/chadb/code
[08:15 PM] ~/code $ cd sub_demo_folder/
[08:15 PM] ~/code/sub_demo_folder $ cat ~/code/sub_demo | bash -
/c/Users/chadb/code
[08:15 PM] ~/code/sub_demo_folder $ cd ~
[08:15 PM] ~ $ cat ~/code/sub_demo | bash -
/c/Users/chadb/code
[08:15 PM] ~ $ cd code
[08:15 PM] ~/code $ cat ~/code/sub_demo | bash -
/c/Users/chadb/code
观察输出值为总是 /c/Users/chadb/code
逃脱 - 有效
[08:15 PM] ~/code $ echo "echo \$PWD" > sub_demo
[08:15 PM] ~/code $ cat sub_demo
echo $PWD
[08:16 PM] ~/code $ cd sub_demo_folder/
[08:19 PM] ~/code/sub_demo_folder $ cat ~/code/sub_demo | bash -
/c/Users/chadb/code/sub_demo_folder
[08:19 PM] ~/code/sub_demo_folder $ cd ~
[08:19 PM] ~ $ cat ~/code/sub_demo | bash -
/c/Users/chadb
[08:19 PM] ~ $ cd code/
[08:19 PM] ~/code $ cat ~/code/sub_demo | bash -
/c/Users/chadb/code
现在观察一下,每次执行命令时都会显示正确的当前的根据需要的目录。