bash 提示和函数内的回显颜色

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6592077/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 00:18:12  来源:igfitidea点击:

bash prompt and echoing colors inside a function

bashfunctioncolorsecho

提问by Andy Ray

I have this in my .bashrc:

我的 .bashrc 中有这个:

LIGHTGREEN="\[3[1;32m\]"
LIGHTRED="\[3[1;31m\]"
WHITE="\[3[0;37m\]"
RESET="\[3[0;00m\]"

function error_test {
    if [[ $? = "0" ]]; then
        echo -e "$LIGHTGREEN"
    else
        echo -e "$LIGHTRED"
    fi
}

PS1="\u$(error_test)@\w$RESET $ "

This seems to make the shell output exactly:

这似乎使 shell 输出完全正确:

username\[\]@~/

username\[\]@~/

The escaping [ and ] around the color codes are showing up in my prompt. If I remove the escape codes from around the colors it works, but then bash line wrapping fails stupendously.

颜色代码周围的转义 [ 和 ] 出现在我的提示中。如果我从它工作的颜色周围删除转义码,但是 bash 换行会惊人地失败。

Note if do PS1="LIGHTGREEN - whatever - $RESET"it works and the [ and ] are not escaped. However, I want to do this inside a function, which seems to be the issue.

请注意PS1="LIGHTGREEN - whatever - $RESET"它是否有效并且 [ 和 ] 没有被转义。但是,我想在一个函数中执行此操作,这似乎是问题所在。

I can't find any good documentation on this. man echodoesn't even list a -e option. Bash seems like it has a lot of undocumented, handmedown knowledge.

我找不到任何关于此的好的文档。man echo甚至没有列出 -e 选项。Bash 似乎有很多未记录的、手工制作的知识。

回答by thedk

I found this topic looking for answer how to set bash color with escaping \[ \]from bash function.

我发现这个主题正在寻找答案如何设置 bash 颜色并\[ \]从 bash 函数中转义。

Actually there is solution. Bash allows to generate PS1prompt each time prompt is rendered.

其实是有解决办法的。Bash 允许在PS1每次呈现提示时生成提示。

set_bash_prompt(){
    PS1="\u@\h $(call_your_function) $>"
}

PROMPT_COMMAND=set_bash_prompt

This way, PS1 will be interpreted each time prompt will be displayed, so it will call function and render properly all escaping sequences including \[ \]which are important for counting length of prompt (e.g. to make command history work correctly).

这样,每次显示提示时都会解释 PS1,因此它将调用函数并正确呈现所有转义序列,包括\[ \]对计算提示长度很重要的序列(例如,使命令历史正常工作)。

Hopefully this will help someone, as I spend half a day to solve this issue.

希望这会对某人有所帮助,因为我花了半天时间来解决这个问题。

回答by MauricioRobayo

Use \001instead of \[and \002instead of \], and be aware of the consequences of usingPROMPT_COMMANDas that method will reset the prompt every single time (which can also be just what you want).

使用\001代替\[\002代替\],并注意使用的后果,PROMPT_COMMAND因为该方法每次都会重置提示(这也可以是您想要的)。

The solution for bash prompt echoing colors inside a function is explained here:

这里解释了 bash 提示在函数内回显颜色的解决方案:

The \[\]are only special when you assign PS1, if you print them inside a function that runs when the prompt is displayed it doesn't work. In this case you need to use the bytes \001and \002

\[\]当你将PS1,如果你把它们打印功能在运行提示在显示时不工作里面只有特殊。在这种情况下,您需要使用字节\001\002

There is also this other answerthat points in the same direction:

还有另一个指向同一方向的答案

bash-specific \[and \]are in fact translated to \001and \002

庆典专用的\[\]其实都是翻译成\001\002

Setting PS1inside a function called by PROMPT_COMMANDas suggested in the accepted aswer resets PS1every single time not allowing other scripts to easily modify your promtp (for example Python virtualnenv activate.sh):

按照接受的 aswer 中的建议在PS1调用的函数中进行设置,每次PROMPT_COMMAND都会重置,PS1不允许其他脚本轻松修改您的 promtp(例如 Python virtualnenv activate.sh):

$ echo $PS1
<your PS1>
$ PS1="(TEST)$PS1"
$ echo $PS1
<(TEST) is not prepended to PS1 if you are using PROMPT_COMMAND as it is reset>

回答by Ignacio Vazquez-Abrams

\[and \]must be used in $PS*directly, rather than just having them output via echo.

\[并且\]必须直接使用$PS*,而不仅仅是让它们通过echo.

LIGHTGREEN="3[1;32m"
LIGHTRED="3[1;31m"
WHITE="3[0;37m"
RESET="3[0;00m"

function error_test {
    if [[ $? = "0" ]]; then
        echo -e "$LIGHTGREEN"
    else
        echo -e "$LIGHTRED"
    fi
}

PS1="\u\[$(error_test)\]@\w\[$RESET\] $ "

回答by l0b0

Here's the coloured exit code portion of my PS1code:

这是我的PS1代码的彩色退出代码部分:

color_enabled() {
    local -i colors=$(tput colors 2>/dev/null)
    [[ $? -eq 0 ]] && [[ $colors -gt 2 ]]
}

BOLD_FORMAT="${BOLD_FORMAT-$(color_enabled && tput bold)}"
ERROR_FORMAT="${ERROR_FORMAT-$(color_enabled && tput setaf 1)}"
RESET_FORMAT="${RESET_FORMAT-$(color_enabled && tput sgr0)}"

# Exit code
PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s $BOLD_FORMAT $ERROR_FORMAT $exit_code $RESET_FORMAT " ")'

Screenshot (with one Subversion repository path anonymized): Color coded output

屏幕截图(有一个匿名的 Subversion 存储库路径): 彩色编码输出

回答by ChrisAshton84

I realize this is an old topic, but I just got this working with functions. The trick is to split the printing and non-printing parts of the function up so you can correctly bracket the non-printing parts with [ ]. Normally I like my ERROR.. line to be separate (and this isn't a problem then), but this also works correctly if everything is all in one line.

我意识到这是一个古老的话题,但我刚刚开始使用函数。诀窍是将函数的打印和非打印部分分开,这样您就可以用 [ ] 正确地将非打印部分括起来。通常我喜欢我的 ERROR.. 行是分开的(这不是问题),但如果一切都在一行中,这也能正常工作。

Note that I return the previous $? value from each sub-shell so $? gets propagated from one to the next.

请注意,我返回了之前的 $? 每个子壳的值所以 $? 从一个传播到另一个。

PS1="\n\
\[\`
  cja_prv_retval=$?;
  if [ $cja_prv_retval != 0 ];
     then echo -ne $E_ERROR;
  fi
  exit $cja_prv_retval
\`\]\
\`
  cja_prv_retval=$?;
  if [ $cja_prv_retval != 0 ];
     then echo -ne \"ERROR: RETURN CODE $cja_prv_retval\";
  fi
  exit $cja_prv_retval
\`\
\[\`
  cja_prv_retval=$?;
  if [ $cja_prv_retval != 0 ];
     then echo -ne $E_RESET;
  fi
  exit $cja_prv_retval
\`\]\
${P_RESET}${P_GRAY}\! \t ${P_RED}\u${P_GRAY}@${P_GREEN}\h ${P_YELLOW}\w ${P_CYAN}   ══>${P_RESET} "

This gives me either

这给我要么

2021 12:28:05 cja@morpheus04 ~ ══>

if there is no error, or

如果没有错误,或者

ERROR: RETURN CODE 1 2021 12:28:16 cja@morpheus04 ~ ══>

if there is an error. Everything is correctly spaced (multi-line history editing works correctly).

如果有错误。一切都正确间隔(多行历史编辑工作正常)。

回答by Luis Lavaire

This will work fine.

这将正常工作。

LIGHTGREEN="\e[32m"
LIGHTRED="\e[31m"
RESET="\e[0m"

error_test () {
    if [[ $? = "0" ]]; then
        echo -e "$LIGHTGREEN"
    else
        echo -e "$LIGHTRED"
    fi
}
export PS1=$(printf "$(error_test) $(whoami)@${RESET}$(pwd) ")