Bash PS1:来自外部命令的非打印字符的换行问题

Lee*_*ton 9 linux bash escaping prompt command-prompt

我正在使用外部命令来填充我的bash提示符,每次评估PS1时都会运行该提示符.但是,当此命令输出不可打印的字符(如颜色转义码)时,我遇到了问题.这是一个例子:

$ cat green_cheese.sh 
#!/bin/bash
echo -e "\033[32mcheese\033[0m"

$ export PS1="\$(./green_cheese.sh) \$"
cheese $ # <- cheese is green!
cheese $ <now type really long command>
Run Code Online (Sandbox Code Playgroud)

与非打印字符的PS1提示处理的典型方法是将它们封闭在\[和\]转义序列.问题是如果你从外部命令执行此操作,PS1解释器不会解析这些转义:

$ cat green_cheese.sh 
#!/bin/bash
echo -e "\[\033[32m\]cheese\[\033[0m\]"
$ export PS1="\$(./green_cheese.sh) \$"
\[\]cheese\[\] $ # <- FAIL!
Run Code Online (Sandbox Code Playgroud)

是否有一个特定的转义序列,我可以使用外部命令来实现所需的结果?或者有没有办法我可以手动告诉提示符将提示宽度设置为多少个字符?

假设我可以从外部命令打印任何我喜欢的内容,并且该命令可以非常智能(例如,计算输出中的字符).我也可以export PS1=...根据需要使命令变得复杂.但是,颜色的转义码必须来自外部命令.

提前致谢!

che*_*ner 19

我无法确切地告诉您为什么这样做有效,但是在您的提示中替换\[以及从它们生成\]的实际字符bash:

echo -e "\001\033[32m\002cheese\001\033[0m\002"
Run Code Online (Sandbox Code Playgroud)

[我从一些我现在找不到的Stack Overflow帖子中学到了这一点.]

如果我不得不猜测,那就是在执行提示中嵌入的命令之前bash替换\[并\]使用两个ASCII字符,这样到时候green_cheese.sh完成时,bash正确处理包装器为时已晚,因此它们会被字面处理.避免这种情况的一种方法是使用PROMPT_COMMAND动态构建提示,而不是将可执行代码嵌入到值中PS1.

prompt_cmd () {
    PS1="$(green_cheese.sh)"
    PS1+=' \$ '
}

PROMPT_COMMAND=prompt_cmd
Run Code Online (Sandbox Code Playgroud)

通过这种方式,\[并\]添加到PS1是当它定义的,而不是当它被评估,这样你就不需要使用\001和\002直接.

  • 你完全正确.`\ 001`和`\ 002`,又名RL_PROMPT_START_IGNORE和RL_PROMPT_END_IGNORE,记录不完整[readline feature](http://git.savannah.gnu.org/cgit/readline.git/tree/display.c?id= fb914b20839322c962918590b3ea449555d7d9f9#N262).Bash将`\ [\ .. \]`转换为`\ 001 ..\002` for Readline,但忽略了逃避现有的,以便这个实现细节泄漏(并且它非常有用,你很难称之为bug). (5认同)