在Bash提示符的函数中转义非打印字符


20

在Bash提示符(PS1变量)中,我正在调用一个函数来向提示添加文本: export PS1="\u@\h \$(my_function) \$ "

但是,提示中的函数包含ANSI颜色代码,这些代码根据函数的输出而变化(有时是红色,有时是绿色)。添加“ \[ “PS1变量应该将这些代码转义为非打印,但是如果我这样做的话 echo 在功能中,“ \[ “在提示中按字面打印。

如何从函数中转义这些ANSI颜色代码以用于bash提示符?

Answers:


31

的ReadLine 图书馆接受 \001\002 (ASCII SOH和STX )作为不可打印的文本分隔符。这些也适用于任何使用的应用程序 的ReadLine

lib/readline/display.c:243 庆典 源代码:

243 /* Current implementation:
244         \001 (^A) start non-visible characters
245         \002 (^B) end non-visible characters
246    all characters except \001 and \002 (following a \001) are copied to
247    the returned string; all characters except those between \001 and
248    \002 are assumed to be `visible'. */

庆典 -具体 \[\] 事实上已被翻译成 \001\002y.tab.c:7640


注意:如果您使用 庆典 printf 要么 echo -e,如果你的文字有 \001 要么 \002 在一个数字之前,你会遇到一个 庆典 处理八进制转义时导致它吃掉一个数字的错误 - 也就是说, \00142 将被解释为八进制014(后跟ASCII“2”),而不是正确的八进制01(后跟ASCII“42”)。因此,请使用十六进制版本 \x01\x02 代替。


就是这样! echo -e "\001\e[31m\002RED" 按预期工作。谢谢!
MidnightLightning

抱歉复活了一个答案,但是什么是dash / ash / sh的等价物?
Hosh Sadiq

1

这是一个很好的完整答案。我不得不做更多的挖掘来弄清楚\ 001等必须去哪里。希望这可以帮助。

# Color prompt for git
reset=$(tput sgr0)
boldgreen=$(tput setaf 2)$(tput bold)
cyan=$(tput sgr0)$(tput setaf 6)
boldred=$(tput setaf 1)$(tput bold)
boldwhite=$(tput setaf 7)$(tput bold)
boldyellow=$(tput setaf 3)$(tput bold)

PARENCLR=$'\001\e[0;36m\002'
BRANCHCLR=$'\001\e[1;33m\002'

alias branchname="git branch 2>/dev/null | grep '*' | sed 's/* \(.*\)/ ${PARENCLR}(${BRANCHCLR}\1${PARENCLR}\)/'"

GIT_STATUS='$(branchname)'

PROMPT_CHAR="\$"
PS1="\[$boldgreen\]\u\[$cyan\]::\[$boldred\]\h \[$cyan\]{\[$boldwhite\].../\W\[$cyan\]}\[$reset\]$GIT_STATUS\[$reset\]$PROMPT_CHAR "

我在这里设置它的方式,只有你在git分支中才会出现git分支括号,否则它是空白的。


0

基于 grawity的答案 ,以下将用ASCII括起ANSI控制序列 SOH^A )和 STX^B )相当于 \[\] 分别:

function readline_ANSI_escape() {
  if [[ $# -ge 1 ]]; then
    echo "$*"
  else
    cat  # Read string from STDIN
  fi | \
  perl -pe 's/(?:(?<!\x1)|(?<!\\\[))(\x1b\[[0-9;]*[mG])(?!\x2|\\\])/\x1\1\x2/g'
}

使用它像:

$ echo $'\e[0;1;31mRED' | readline_ANSI_escape

要么:

$ readline_ANSI_escape "$string"

作为奖励,多次运行该功能将不会重新逃脱已经转义的控制代码。


-2

如果要在提示中使用它们,则需要执行此操作 \[。但是如果你想在回声中使用它,你必须使用它 \033[


嗯......添加\ 033 [在ANSI命令之前(“\ e [31m”)和\ 033]之后,它似乎使提示中的下一个打印字符无法打印。
MidnightLightning

1
你不想在它之后做\ 033]。 \ 033 [31m开始颜色,之后您需要将其设置为\ 033 [0m
Wuffers
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.