如何在 bash 提示中正确转义 unicode 字符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7112774/
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
How to escape unicode characters in bash prompt correctly
提问by Andy Ray
I have a specific method for my bash prompt, let's say it looks like this:
我的 bash 提示有一个特定的方法,假设它看起来像这样:
CHAR="? "
my_function="
prompt=\" \[$CHAR\]\"
echo -e $prompt"
PS1="$(${my_function}) $ "
To explain the above, I'm builidng my bash prompt by executing a function stored in a string, which was a decision made as the result of this question. Let's pretend like it works fine, because it does, except when unicode characters get involved
为了解释上述内容,我通过执行存储在字符串中的函数来构建我的 bash 提示,这是作为这个问题的结果做出的决定。让我们假装它工作正常,因为它确实如此,除非涉及 unicode 字符
I am trying to find the proper way to escape a unicode character, because right now it messes with the bash line length. An easy way to test if it's broken is to type a long command, execute it, press CTRL-R and type to find it, and then pressing CTRL-A CTRL-E to jump to the beginning / end of the line. If the text gets garbled then it's not working.
我试图找到转义 unicode 字符的正确方法,因为现在它与 bash 行长度混淆。测试它是否已损坏的一种简单方法是键入一个长命令,执行它,按 CTRL-R 并键入以找到它,然后按 CTRL-A CTRL-E 跳到行的开头/结尾。如果文本出现乱码,则它不起作用。
I have tried several things to properly escape the unicode character in the function string, but nothing seems to be working.
我已经尝试了几种方法来正确转义函数字符串中的 unicode 字符,但似乎没有任何效果。
Special characters like this work:
像这部作品这样的特殊人物:
COLOR_BLUE=$(tput sgr0 && tput setaf 6)
my_function="
prompt="\[$COLOR_BLUE\] \"
echo -e $prompt"
Which is the main reason I made the prompt a function string. That escape sequence does NOT mess with the line length, it's just the unicode character.
这是我将提示设为函数字符串的主要原因。该转义序列不会与行长度混淆,它只是 unicode 字符。
采纳答案by tripleee
The \[...\]sequence says to ignore this part of the string completely, which is useful when your prompt contains a zero-length sequence, such as a control sequence which changes the text color or the title bar, say. But in this case, you are printing a character, so the length of it is not zero. Perhaps you could work around this by, say, using a no-op escape sequence to fool Bash into calculating the correct line length, but it sounds like that way lies madness.
该\[...\]序列表示完全忽略字符串的这一部分,当您的提示包含零长度序列(例如更改文本颜色或标题栏的控制序列)时,这很有用。但是在这种情况下,您正在打印一个字符,因此它的长度不为零。也许您可以通过使用无操作转义序列来欺骗 Bash 计算正确的行长度来解决这个问题,但这听起来像是疯了。
The correct solution would be for the line length calculations in Bash to correctly grok UTF-8 (or whichever Unicode encoding it is that you are using). Uhm, have you tried without the \[...\]sequence?
正确的解决方案是在 Bash 中计算行长度以正确理解 UTF-8(或您使用的任何 Unicode 编码)。嗯,你试过没有\[...\]顺序吗?
Edit:The following implements the solution I propose in the comments below. The cursor position is saved, then two spaces are printed, outside of \[...\], then the cursor position is restored, and the Unicode character is printed on top of the two spaces. This assumes a fixed font width, with double width for the Unicode character.
编辑:以下实现了我在下面的评论中提出的解决方案。保存光标位置,然后打印两个空格,在 之外\[...\],然后恢复光标位置,在两个空格的顶部打印Unicode字符。这假定字体宽度固定,Unicode 字符宽度加倍。
PS1='\['"`tput sc`"'\] \['"`tput rc`"'? \] $ '
At least in the OSX Terminal, Bash 3.2.17(1)-release, this passes cursory [sic] testing.
至少在 OSX 终端,Bash 3.2.17(1)-release 中,这通过了粗略的 [sic] 测试。
In the interest of transparency and legibility, I have ignored the requirement to have the prompt's functionality inside a function, and the color coding; this just changes the prompt to the character, space, dollar prompt, space. Adapt to suit your somewhat more complex needs.
为了透明和易读,我忽略了在函数中具有提示功能和颜色编码的要求;这只是将提示更改为字符、空格、美元提示、空格。适应您更复杂的需求。
回答by Andy Ray
@tripleee wins it, posting the final solution here because it's a pain to post code in comments:
@tripleee 赢了,在这里发布最终解决方案,因为在评论中发布代码很痛苦:
CHAR="?"
my_function="
prompt=\" \[`tput sc`\] \[`tput rc`\]\[$CHAR\] \"
echo -e $prompt"
PS1="$(${my_function}) $ "
The trick as pointed out in @tripleee's link is the use of the commands tput scand tput rcwhich save and then restore the cursor position. The code is effectively saving the cursor position, printing two spaces for width, restoring the cursor position to before the spaces, then printing the special character so that the width of the line is from the two spaces, not the character.
@tripleee 的链接中指出的技巧是使用命令tput sc并tput rc保存然后恢复光标位置。该代码有效地保存光标位置,打印两个空格作为宽度,将光标位置恢复到空格之前,然后打印特殊字符,使行的宽度来自两个空格,而不是字符。
回答by shellter
(Not the answer to your problem, but some pointers and general experience related to your issue.)
(不是您问题的答案,而是与您的问题相关的一些指示和一般经验。)
I see the behaviour you describe about cmd-line editing (Ctrl-R, ... Cntrl-A Ctrl-E ...) all the time, even without unicode chars.
我一直看到您描述的有关 cmd 行编辑(Ctrl-R,... Cntrl-A Ctrl-E ...)的行为,即使没有 unicode 字符。
At one work-site, I spent the time to figure out the diff between the terminals interpretation of the TERM setting VS the TERM definition used by the OS (well, stty I suppose).
在一个工作现场,我花时间弄清楚 TERM 设置的终端解释与操作系统使用的 TERM 定义之间的差异(好吧,我想是 stty)。
NOW, when I have this problem, I escape out of my current attempt to edit the line, bring the line up again, and then immediately go to the 'vi' mode, which opens the vi editor. (press just the 'v' char, right?). All the ease of use of a full-fledged session of vi; why go with less ;-)?
现在,当我遇到这个问题时,我会从当前尝试编辑该行的过程中退出,再次启动该行,然后立即进入“vi”模式,这将打开 vi 编辑器。(只需按“v”字符,对吗?)。一个成熟的 vi 会话的所有易用性;为什么少用;-)?
Looking again at your problem description, when you say
再看你的问题描述,当你说
my_function="
prompt=\" \[$CHAR\]\"
echo -e $prompt"
That is just a string definition, right? and I'm assuming your simplifying the problem definition by assuming this is the output of your my_function. It seems very likely in the steps of creating the function definition, calling the function AND using the values returned are a lot of opportunities for shell-quoting to not work the way you want it to.
那只是一个字符串定义,对吧?我假设您通过假设这是您的my_function. 在创建函数定义、调用函数和使用返回的值的步骤中,很有可能导致 shell 引用无法按您希望的方式工作。
If you edit your question to include the my_functiondefinition, and its complete use (reducing your function to just what is causing the problem), it may be easier for others to help with this too. Finally, do you use set -vxregularly? It can help show how/wnen/what of variable expansions, you may find something there.
如果您编辑问题以包含my_function定义及其完整使用(将您的功能减少到导致问题的原因),其他人也可能更容易帮助解决此问题。最后,你set -vx经常使用吗?它可以帮助显示变量扩展的方式/wnen/什么,您可能会在那里找到一些东西。
Failing all of those, look at Orielly termcap & terminfo. You may need to look at the man page for your local systems sttyand related cmds AND you may do well to look for user groups specific to you Linux system (I'm assuming you use a Linux variant).
如果所有这些都失败了,请查看 Orielly termcap 和 terminfo。您可能需要查看本地系统stty和相关 cmds的手册页,并且您最好查找特定于您的 Linux 系统的用户组(我假设您使用的是 Linux 变体)。
I hope this helps.
我希望这有帮助。

