在 PS1 中使用 echo -e 会导致 shell 中出现换行问题

six*_*ude 0 bash prompt

问题

打开命令行提示符:

在此处输入图片说明

多次输入字母 a:

在此处输入图片说明

输入的文本不是换行,而是换行到同一行:

在此处输入图片说明

现在,开始按 b。第二次需要换行时,它将换行到新行:

在此处输入图片说明


是什么导致了这种行为?

像这样使用 PS1 会导致以下行为:

ps1Color="\033[1;35m"
export PS1='$(echo -en $ps1Color) Baz $'
Run Code Online (Sandbox Code Playgroud)

请注意,我想直接使用 echo 而不是颜色的原因是因为我想根据上一个命令的退出状态有条件地添加颜色

直接使用颜色不会导致此行为发生。


我的问题是:

  • 如何使用 echo打印用于 PS1 的颜色代码?
  • 如果我想让我的 PS1 有条件地变成不同的颜色,最好的方法是什么?
  • 为什么我会看到这种行为?

更新

明确地说,我真的想使用 echo 来做到这一点,因为我想有条件地改变颜色。

这是我目前拥有的:

function setPs1Colors_start () {

    local previousExit=$?

    local ps1Color="\033[1;35m"
    local ps1FailBackground="\e[41m"

    echo -en $ps1Color

    if [[ previousExit -ne 0 ]]
    then
        echo -en $ps1FailBackground
    fi

}

function setPs1Colors_end () {
    local ps1DefaultColor="\033[0m"
    echo -en $ps1DefaultColor
}

export PS1='$(setPs1Colors_start)[$(date +%b\-%d\ %k:%M)][$(versionControlInfo)\W]\$$(setPs1Colors_end) '
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 8

\033[1;35m是 7 个字符。bash无法猜测这 7 个字符实际上具有空宽度。如果不是,它会认为它们是 7 列宽。

它(或者更确切地说readline是它使用的底层行编辑器)想知道屏幕上的当前位置是什么,因为当您使用编辑键时,它使用光标定位序列(向上、向下、向左、向右)移动光标。

所以你必须告诉它提示中的哪些字符不会移动光标。使用bash,这是通过使用\[...\]which 告诉外壳里面的东西宽度为零来完成的。

另请注意,提示扩展 inbash确实识别\e为 ESC 字符,因此您不必使用echo -e. 你可以这样做:

PS1='\[\e[1;35m\] blah $ '
Run Code Online (Sandbox Code Playgroud)

如果你必须使用echo,或者更好printf,你会这样做:

PS1='\[$(if ...; then printf "$color1"; fi)\] blah $ '
Run Code Online (Sandbox Code Playgroud)

或者:

PS1='$(if ...; then printf "\[$color1\]"; fi) blah $ '
Run Code Online (Sandbox Code Playgroud)

zsh,相当于bash\[...\]%{...%}tcsh的,但zsh有指令来改变人物属性,所以你宁愿做:

PS1='%B%F{magenta}blah $ '
Run Code Online (Sandbox Code Playgroud)

对于粗品洋红色前景。它也有一些形式的条件测试,包括 on $?,所以你的redif 错误,green 否则可以写成:

PS1='%F{%(?:green:red%)}blah%f $ '
Run Code Online (Sandbox Code Playgroud)

tcsh%B,但没有%F{color}。所以在那里,你会使用:

set prompt = '%{\e[1;35m%}blah $ '
Run Code Online (Sandbox Code Playgroud)

ksh88or 中pdksh,你会这样做:

PS1=$(printf '\5\r\5\33[1;35m\5blah $ ')
Run Code Online (Sandbox Code Playgroud)

这将一个字符(此处为 0x5)定义为转义字符。然后通过在它们之间包含文本,您告诉外壳它不可见。您可以使用除 0x5 之外的任何字符,但它不能以其他方式出现在您的提示中,并且除了在 mksh 中之外,它必须被终端忽略,因为 shell 确实会写入它(连同 CR 字符)。

ksh93仅使用一个光标定位序列:(BS将光标向左移动一列)。向右移动,它只是重绘相同的字符。所以它不需要知道光标位置,只需要知道你输入的每个字符的宽度。只要终端自己在边距处换行就可以工作(例如,因此无法正常工作terminator)。如果您有控制序列的提示,一个副作用是您的制表位不会正确对齐。