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

问题描述 投票:0回答:7

我的 .bashrc 中有这个:

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

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

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

这似乎使 shell 输出准确:

username\[\]@~/

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

注意如果这样做

PS1="LIGHTGREEN - whatever - $RESET"
它可以工作并且 [ 和 ] 不会被转义。但是,我想在函数内执行此操作,这似乎是问题所在。

我找不到任何关于此的好的文档。

man echo
甚至没有列出 -e 选项。 Bash 似乎有很多未记录的、传下来的知识。

bash function colors echo
7个回答
61
投票

我发现这个主题正在寻找如何通过从 bash 函数转义

\[ \]
来设置 bash 颜色的答案。

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

PS1
提示。

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

PROMPT_COMMAND=set_bash_prompt

这样,每次显示提示时都会解释 PS1,因此它将调用函数并正确渲染所有转义序列,包括

\[ \]
,这对于计算提示长度很重要(例如,使命令历史记录正确工作)。

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


43
投票

使用

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

bash 提示符在函数内回显颜色的解决方案解释为here:

\[
\]
仅当您分配 PS1 时才特殊,如果您打印它们 在显示提示时运行的函数内部却没有 工作。在这种情况下,您需要使用字节
\001
\002

还有这个其他答案指向相同的方向:

bash 特定的

\[
\]
实际上被翻译为
\001
\002

按照接受的问题中的建议,在

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>

8
投票

\[
\]
必须直接在
$PS*
中使用,而不是仅仅通过
echo
输出。

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

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

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

0
投票

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

注意我返回了之前的$?每个子 shell 的值是 $?从一个传播到下一个。

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} "

这给了我一个

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

如果没有错误,或者

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

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


0
投票

这是我的

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 " ")'

屏幕截图(其中一个 Subversion 存储库路径已匿名): Color coded output


0
投票

这会很好用。

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) ")

0
投票

另一个答案已经指出需要将

\[...\]
转换为
\001...\002
。要动态地执行此操作,您可以使用 Bash 的
@P
变量转换来“像提示一样”评估变量。这会评估颜色和粗体等的转义序列,例如
printf '%b'
echo -e
,但最重要的是,它还评估特定于提示的
\[...\]
构造。

对于问题中给出的函数,只需要一个小小的改变,将

echo -e "$foo"
更改为
echo "${foo@P}"
(下面我使用
printf '%s'
来明确避免echo的换行符)。

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

function error_test {
    if [[ $? = "0" ]]; then
        printf '%s' "${LIGHTGREEN@P}"
    else
        printf '%s' "${LIGHTRED@P}"
    fi
}

PS1="\u\$(error_test)@\w$RESET \$ "
© www.soinside.com 2019 - 2024. All rights reserved.