Shell提示符行包装问题

41

我在OS X(10.5.7)终端中破坏了我的Bash Shell提示符。

这是我配置的PS1:

PS1='\[\e[1;32m\]\h\[\e[0m\]:\[\e[1;34m\]\w\[\e[0m\]\$ '
据我所知,我已经正确地转义了颜色命令。但是当我在命令历史记录中上下滚动时,如果历史命令换行成多行,则经常出现换行问题。
我将提示简化为以下内容:
PS1='\[\e[1m\]\h:\w\$ \[\e[0m\]'
PS2='> '

我仍然看到如下内容:

localhost:~/Library/Application Support/Firefox/Profiles/knpmxpup.Defau
lt/extensions/{1A2D0EC4-75F5-4c91-89C4-3656F6E44B68}$ expocd \{1A2D0EC4-7
5F5-4c91-89C4-3656F6E                                           export PS1="\[
\e[1;32m\]\h\[\e[0m\]:                                          cd Library/Appl
ication\ Support/

我也尝试了将\e替换为\033,上面的PS2只是提供信息,我没有改变它的默认安装。如果我完全删除颜色代码,那么一切正常工作,有什么想法吗?


$TERM是什么?如果我没记错的话,Terminal.app的终端仿真并不完全匹配终端数据库中的任何内容,但dtterm很接近。 - ephemient
我在 Fedora8 上的 bash 3.2.33 上尝试了你的 PS1。即使动态更改终端的宽度,长行也能正常工作。当更改高度时,它会打印重复的行,但是使用 Ctrl-L 可以解决。可能是一个 bug... - neuro
@ephemient 我的 $TERM 是 'xterm-color'。 - Rob
如果使用 TERM=dtterm 仍然出现问题(可以在终端的某个设置中进行配置),那么我不知道了。我已经好几年没有接触过 OS X 了。 - ephemient
9个回答

51

我现在使用这个PS1并取得了不错的效果:

green=$(tput setaf 2)
blue=$(tput setaf 4)
bold=$(tput bold)
reset=$(tput sgr0)
PS1="\[$green$bold\]\h\[$reset\]:\[$blue$bold\]\w\[$reset\]\$ "

浏览我的命令历史记录时,似乎现在可以处理换行了。但是自从这个问题被提出以来,我还将我的OS X升级到了10.6.3。


1
谢谢!这个问题困扰我很长时间了。我认为诀窍在于你的颜色处理方法。我之前使用的颜色样式是这样的(这个是蓝色加粗):\e[0;34m - Cory Gagliardi
1
这是针对OS X的真正答案,包括最新的Mavericks和Yosemite,谢谢。 - Joey T
+1 指的是支持 El Capitan 操作系统,tput setaf 是终端颜色控制命令。\[$green\] 语法适合我使用;我之前在 PROMPT_COMMAND 中使用了 ${green} 导致了奇怪的同行换行问题。 - mhulse
在macOS Sierra上,标准使用\e[38;5;220m会导致换行问题,但是简单地用\[ ... \]包装似乎可以解决这个问题。 - Pascal
@Pascal(以及未来在这里的其他人),原始问题本应该可以工作,但当时bash存在一个bug。https://lists.gnu.org/archive/html/bug-bash/2009-07/msg00016.html - Captain Man

21

使用tput生成我的颜色代码,如此FAQ所述: http://mywiki.wooledge.org/BashFAQ/037 我的提示符滚动得更好了。但是我也在新版本的OS X上,所以我不确定哪个可能已经修复了这个问题。 - Rob

8
Bash中的换行问题并不新鲜。你的PS1应该按原样工作,但是Bash 3.2.49存在一个错误。请参考邮件列表,其中有另一个与此相关的错误,已经确认在4.0中已修复
你只能使用\[\]标记不可打印字符,其余部分必须由提示代码完成。

谢谢,我只是想确认我已经正确转义了。 - Rob
1
仅供从Google进入此处的人参考,原始帖子没有任何问题。关键是使用\[\](Rob已经使用了)。如果您想解决自己可能犯的错误(我也一样哈哈),请参见此处的答案(尽管标题暗示它不是针对Mac的)。 - Captain Man

2
似乎你已经正确转义和封闭了序列。
我通常使用的一个解决方法是在结尾添加“\n”。我发现这样更清晰,减少了换行问题。我的PS1的确切结尾是:
'\n\[\033[0;30m\]$\[\033[0m\]

一篇很好的教程,你可能已经知道了:

Bash提示符教程


你是正确的。当时只是Bash中的一个bug。 - Captain Man

1
我注意到即使在PS1PROMPT环境变量中没有特殊字符,提示光标位置仍然存在一些问题。
如果我们输出的文件末尾没有换行符号,它会混淆提示符。
您可以通过执行以下操作来复现此问题: curl https://gist.githubusercontent.com/martinos/d4aa0a7d4d752b0d0d9f/raw/3198c39f84a080c44227a084a19fb3a0bb661ee5/wrapping_issue.txt 多次按上箭头键,您将看到提示符混淆的情况。
您可以看到一个示例:

https://asciinema.org/a/9mtjhi9dib6md4ocsbw210cca

当出现这种情况时,只需按下<CTRL-C>,提示符就会恢复正常。
请注意,ZShell没有这个问题。

0
这是我的代码:我觉得它是我找到的最好的,但是我最初找到它的网站缺少一个转义字符,导致了换行问题。我对它进行了一些调整,最终让它正常工作了。它可以显示你的用户、路径和分支信息,并且颜色对比度很好。
export PS1='\[\e[1;37m\]\[\e[1;32m\]\u\[\e[0;39m\]:\[\e[1;33m\]\w\[\e[0;39m\]\[\e[1;35m\]$(__git_ps1 " (%s)")\[\e[0;39m\] \[\e[1;37m\]|\[\e[0;39m\]\$'

另外,添加

GIT_PS1_SHOWDIRTYSTATE=true

在分支“脏”(存在待提交的更改)时显示标记。
export HISTCONTROL=ignoredups

在通过Bash历史向上滚动时忽略重复内容也很有用。

bind "set completion-ignore-case on" 

也有帮助。

最后,

shopt -s checkwinsize

如果问题仍然存在,可能会在OSX上有所帮助。


0

供将来参考,这是我使用的内容:

export PS1="\[\033[0;31m\][\u@Project:\w]$\[\033[0m\] "

这将显示我的命令提示符为:

[ec2-user@Project:~]$

帮助我区分生产和开发网站。


3
这与提问者的问题有什么关系? - Tim Seguine

0

'shopt -s checkwinsize' 对于 Cygwin 的换行问题也有效。


0
如果您正在使用标题栏技巧"\e]2;titlebar\a",请确保也进行转义:"\[\e]2;titlebar\a\]"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接