![在 Bash 提示符的函数中转义非打印字符](https://linux22.com/image/1280635/%E5%9C%A8%20Bash%20%E6%8F%90%E7%A4%BA%E7%AC%A6%E7%9A%84%E5%87%BD%E6%95%B0%E4%B8%AD%E8%BD%AC%E4%B9%89%E9%9D%9E%E6%89%93%E5%8D%B0%E5%AD%97%E7%AC%A6.png)
在 Bash Prompt(PS1 变量)中,我调用一个函数来向提示符中添加文本:export PS1="\u@\h \$(my_function) \$ "
但是,提示中的函数包含根据函数输出而变化的 ANSI 颜色代码(有时为红色,有时为绿色)。将“ \[
”添加到 PS1 变量应该会将这些代码转义为不可打印,但如果我echo
在函数中执行此操作,“ \[
”会在提示中逐字打印。
如何在函数中转义这些 ANSI 颜色代码以在 Bash 提示符中使用?
答案1
这阅读行库接受\001
(\002
ASCIISOH 和 STX) 作为不可打印的文本分隔符。这些也适用于使用阅读行。
从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
和。\002
y.tab.c:7640
注意:如果您使用狂欢或,如果你的文本在数字前有 或 ,你会printf
碰到一个echo -e
\001
\002
狂欢处理八进制转义时,错误导致它多吃了一个数字 - 也就是说,\00142
将被解释为八进制 014(后跟 ASCII“2”),而不是正确的八进制 01(后跟 ASCII“42”)。因此,请使用十六进制\x01
版本\x02
。
答案2
这是一个很好的完整答案。我不得不做更多的挖掘才能弄清楚 \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 分支括号才会出现,否则它是空白的。
答案3
基于gravity 的回答,以下将用 ASCII SOH
( ^A
) 和STX
( ^B
) 括起 ANSI 控制序列,它们分别等同于\[
和\]
:
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"
另外,多次运行该函数不会重新转义已经转义的控制代码。
答案4
如果您想在提示中使用它们,那么您确实需要执行\[
。但是如果您想在回显中使用它,您必须使用\033[
。