如何正确地在bash提示符中转义unicode字符

时间:2011-08-18 19:08:24

标签: bash unicode prompt

我的bash提示符有一个特定的方法,让我们说它看起来像这样:

CHAR="༇ "
my_function="
    prompt=\" \[\$CHAR\]\"
    echo -e \$prompt"

PS1="\$(${my_function}) \$ "

为了解释上述情况,我通过执行存储在字符串中的函数来构建我的bash提示符,这是由this question作出的决定。让我们假装它工作正常,因为它确实如此,除非涉及到unicode字符

我正在尝试找到逃脱unicode角色的正确方法,因为现在它与bash行长度混淆。测试它是否被破坏的简单方法是键入一个长命令,执行它,按CTRL-R并键入以找到它,然后按CTRL-A CTRL-E跳转到该行的开头/结尾。如果文本出现乱码,那么它就无法正常工作。

我已经尝试了几个方法来正确地转义函数字符串中的unicode字符,但似乎没有任何工作。

像这样的特殊角色:

COLOR_BLUE=$(tput sgr0 && tput setaf 6)

my_function="
    prompt="\\[\$COLOR_BLUE\\] \"
    echo -e \$prompt"

这是我提示函数字符串的主要原因。那个转义序列不会弄乱行长度,它只是unicode字符。

3 个答案:

答案 0 :(得分:2)

\[...\]序列表示完全忽略字符串的这一部分,这在提示包含零长度序列时非常有用,例如更改文本颜色或标题栏的控制序列。但在这种情况下,您正在打印一个字符,因此它的长度不为零。也许你可以解决这个问题,比如使用一个无操作的转义序列来欺骗Bash来计算正确的行长度,但听起来就像疯狂一样。

正确的解决方案是在Bash中进行行长度计算以正确地识别UTF-8(或者您正在使用的任何Unicode编码)。嗯,你试过没有\[...\]序列吗?

编辑:以下内容实现了我在下面的评论中提出的解决方案。保存光标位置,然后在\[...\]之外打印两个空格,然后恢复光标位置,并在两个空格的顶部打印Unicode字符。假定字体宽度固定,Unicode字符的宽度为双倍。

PS1='\['"`tput sc`"'\]  \['"`tput rc`"'༇ \] \$ '

至少在OSX终端,Bash 3.2.17(1) - 发布,这通过了粗略的[sic]测试。

为了透明和易读,我忽略了在函数内部使用提示功能和颜色编码的要求;这只是将提示更改为字符,空格,美元提示,空格。适应您更复杂的需求。

答案 1 :(得分:2)

@tripleee获胜,在此发布最终解决方案,因为在评论中发布代码很痛苦:

CHAR="༇"
my_function="
    prompt=\" \\[`tput sc`\\]  \\[`tput rc`\\]\\[\$CHAR\\] \"
    echo -e \$prompt"

PS1="\$(${my_function}) \$ "

@ tripleee链接中指出的技巧是使用命令tput sctput rc来保存然后恢复光标位置。代码有效地保存了光标位置,为宽度打印了两个空格,将光标位置恢复到空格之前,然后打印特殊字符,使得行的宽度来自两个空格,而不是字符。

答案 2 :(得分:0)

(不是您的问题的答案,而是与您的问题相关的一些指示和一般经验。)

即使没有unicode字符,我也会一直看到你描述的关于cmd-line编辑(Ctrl-R,... Cntrl-A Ctrl-E ...)的行为。

在一个工作现场,我花了一些时间来弄清楚TERM设置的终端解释与操作系统使用的TERM定义之间的差异(好吧,我想是stty)。

现在,当我遇到这个问题时,我逃脱了当前编辑该行的尝试,再次启动该行,然后立即进入'vi'模式,打开vi编辑器。 (按'v'字符,对吧?)。所有易于使用的完整的vi会话;为什么少用; - )?

再看一下你的问题描述,当你说

my_function="
    prompt=\" \[\$CHAR\]\"
    echo -e \$prompt"

这只是一个字符串定义,对吗?我假设这是你my_function的输出,我假设你简化了问题定义。在创建函数定义的步骤中,调用函数和使用返回的值很有可能使shell引用无法按照您希望的方式工作。

如果您编辑问题以包含my_function定义及其完整用途(将功能简化为导致问题的原因),其他人也可能更容易帮助解决此问题。最后,你经常使用set -vx吗?它可以帮助显示/ wnen /变量扩展的内容,你可以在那里找到一些东西。

未通过所有这些,请查看Orielly termcap & terminfo。您可能需要查看本地系统stty和相关cmds的手册页,并且您可以很好地查找特定于Linux系统的用户组(我假设您使用的是Linux版本)。

我希望这会有所帮助。