【问题标题】:How to escape unicode characters in bash prompt correctly如何在 bash 提示符中正确转义 unicode 字符
【发布时间】:2011-10-30 01:52:35
【问题描述】:

我的 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 字符。

【问题讨论】:

    标签: bash unicode prompt


    【解决方案1】:

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

    我一直看到您描述的有关命令行编辑(Ctrl-R,... Cntrl-A Ctrl-E ...)的行为,即使没有 unicode 字符也是如此。

    在一个工作地点,我花时间找出终端解释 TERM 设置与操作系统使用的 TERM 定义之间的差异(好吧,我想是 stty)。

    现在,当我遇到这个问题时,我会退出当前编辑行的尝试,重新启动该行,然后立即进入“vi”模式,这会打开 vi 编辑器。 (只按 'v' 字符,对吗?)。完整的 vi 会话的所有易用性;为什么要少;-)?

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

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

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

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

    所有这些都失败了,看看Orielly termcap & terminfo。您可能需要查看本地系统的手册页 stty 和相关 cmd,并且您最好查找特定于您的 Linux 系统的用户组(我假设您使用的是 Linux 变体)。

    我希望这会有所帮助。

    【讨论】:

    • stty(1) 到底和这里有什么关系?
    【解决方案2】:

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

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

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

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

    至少在 OSX 终端 Bash 3.2.17(1)-release 中,这通过了粗略的 [原文如此] 测试。

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

    【讨论】:

    • 我试过不使用 \[ \] 并且得到相同的乱码结果。但是,如果我用像 x 这样的普通字符替换 ༇,我看不到问题(同样,不使用转义序列)。我也尝试将△作为不同的角色,但同样的事情
    • 你也许可以将有问题的序列包装在一对curses命令中,比如tput sc,打印两个空格,tput rc,打印你的Unicode字符。这两个空格(或其他具有正确宽度的序列)必须在\[...\] 之外,其余的都在里面。另见tldp.org/HOWTO/Bash-Prompt-HOWTO/x405.html
    【解决方案3】:

    @tripleee 获胜,在这里发布最终解决方案,因为在 cmets 中发布代码很痛苦:

    CHAR="༇"
    my_function="
        prompt=\" \\[`tput sc`\\]  \\[`tput rc`\\]\\[\$CHAR\\] \"
        echo -e \$prompt"
    
    PS1="\$(${my_function}) \$ "
    

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

    【讨论】:

    • 嵌套变量是怎么回事?将值分配给 prompt 只是给 echo 并丢弃它似乎特别浪费。
    • 我从一个更大的函数中提供了一个 sn-p 来显示用例。整个事情(现在工作,感谢你)是我文件底部的大字符串:git、svn 和 hg 信息在提示中格式精美:github.com/DelvarWorld/configs/blob/master/.bashrc
    猜你喜欢
    • 2018-12-16
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-28
    相关资源
    最近更新 更多