如果输出没有以换行符结尾,彩色 bash 提示符将覆盖前一个命令的输出

如果输出没有以换行符结尾,彩色 bash 提示符将覆盖前一个命令的输出

在我的系统上,当使用彩色提示时,如果输出的最后一个字符不是换行符,则前一个命令输出的最后一行将被覆盖。

例如:使用默认的、非彩色的 bash 提示符,我们有:

[myusername@myhostname 目录名]$ echo -n foo-bar
foo-bar[我的用户名@我的主机名 目录名]$

这是预料之中的。

但是,使用以下彩色提示:

PS1='\[\033[1;32m\]\u@\h\[\033[0m\]:\[\033[1;34m\]\w\[\033[0m\]\$ '

我们有(这里显示没有颜色):

myusername@myhostname:~/path/to/dirname$ echo -n foo-bar
myusername@myhostname:~/path/to/dirname$ rname$

光标现在位于行中的最后一个“r”。在提示符下输入一些字符会覆盖最后一个“rname$”。最终结果是,如果前一个命令的输出不是以换行符结尾,我就看不到它是什么。这是最重要的修复问题。多余字符出现的方式,但可以覆盖,这并不困扰我,但如果能修复就更好了。

我已经尝试使用 bash 文档中的其他彩色提示,以及来自其他超级用户答案的​​有关彩色提示的一些彩色提示,它们的行为完全相同。

$ bash --version
GNU bash,版本 3.1.17(1)-发布(x86_64-redhat-linux-gnu)
版权所有 (C) 2005 自由软件基金会,Inc.

不确定,但我认为是 CentOS,不知道是什么版本。给我一个检查操作系统的命令,我会运行它。

答案1

我首选的解决方案是让提示符始终以换行符开头。这样,我在最后一个命令输出之间总会有一个空行(当然,除了这种情况),这对我来说感觉更自然。最糟糕的情况是,我不会像您看到的那样覆盖文本,而是在中间没有空行。除非您尝试了一段时间并且无法忍受空行,否则我强烈推荐它。

PS1='\n\[\033[1;32m\]\u@\h\[\033[0m\]:\[\033[1;34m\]\w\[\033[0m\]\$ '

如果您愿意的话,还有一个额外的建议:我还使用多行提示符,使命令行在换行(或滚动,如果您的终端或 shell 配置为换行)之前尽可能长。我还想知道历史行号。这两个结合起来:

PS1='\n\[\033[1;32m\]\u@\h\[\033[0m\]:\[\033[1;34m\]\w\[\033[0m \!\]\n\$ '

最后,我还喜欢在运行命令之前和之后打印时间戳。我使用的简化版本是:

export PROMPT_COMMAND="date +\"%Y-%m-%d %H:%M:%S (%s)\"; trap 'date +\"%Y-%m-%d %H:%M:%S (%s)\"; trap DEBUG' DEBUG"

头晕了吗?:)

答案2

一个简单而优雅的解决方案是检查光标是否在第一列,如果不是,则发出换行符。我已经为另一个问题写了这个答案,你可以看看:https://serverfault.com/a/1131155/539096

以下是该答案的简要内容:

您可以使用以下命令检测光标位置:IFS=';' read -sdR -p $'\E[6n' ROW COL
变量COL保存光标所在的当前列。如果$COL不等于 1,则在设置 PS1 变量之前添加换行符。

这是我的实现:

_set_prompt() {
    IFS=';' read -sdR -p $'\E[6n' ROW COL # Get cursor position
    [ $COL -ne 1 ] && echo '' # Add newline if cursor is not at 1st column
    PS1="........." # Your PS1 variable
}

PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND; }'_set_prompt'

大多数现成的提示允许自定义,因此您可以轻松添加此检查。

相关内容