BASH 中的变量替换和 CJK 字符之间的冲突

BASH 中的变量替换和 CJK 字符之间的冲突

我在 BASH shell 中遇到了变量替换问题。
假设你定义了一个变量a。然后命令

    $> echo ${a//[0-4]/}

打印其值并删除所有介于 0 和 4 之间的数字:

    $> a="Hello1265-3World"
    $> echo ${a//[0-4]/}
    Hello65-World

这似乎工作正常,但让我们看一下下一个例子:

    $> b="你1265-3好"
    $> echo ${b//[0-4]/}
    你1265-3好

替换没有发生:我认为这是因为b包含 CJK 字符。此问题扩展到所有涉及方括号的情况。令人惊讶的是,在两种情况下,不使用方括号的变量替换都可以正常工作:

    $> a="Hello1265-3World"
    $> echo ${a//2/}
    Hello165-3World
    $> b="你1265-3好"
    $> echo ${b//2/}
    你165-3好

这是一个错误还是我遗漏了什么?

我使用 Lubuntu 12.04,终端是lxterminalecho $BASH_VERSION返回 4.2.24(1)-release。

编辑: 安德鲁·约翰逊在他的评论中说,在4.2.37(1)-release 中,该命令工作正常。我想知道这是否是其特定 4.2.24(1)-release 版本的gnome-terminal问题。lxterminal

编辑:我在 Lubuntu 12.04 上尝试过,gnome-terminal但问题仍然存在......

答案1

简短回答:

设置 LC_ALL=C 以获得您期望的行为

pauhel@permafrost:~$ b="你1265-3好"
paul@permafrost:~$ echo ${b//[0-2]/}
你1265-3好
paul@permafrost:~$ export LC_ALL=C
paul@permafrost:~$ echo ${b//[0-2]/}
你65-3好

长答案:

您期望的行为依赖于排序规则,排序规则依赖于语言环境/OS 实现。POSIX 标准明确未定义排序规则,但 C 语言环境除外。(Bash 为此调用了一个外部库,据猜测,如果仅存在 ASCII 字符,则似乎会恢复为 ASCII 排序)。

更高版本的 bash 有一个 shell 选项,可让您指定您期望的内容。

看:

https://groups.google.com/forum/#!topic/gnu.bash.bug/S6cN9KI4vK4/discussion

了解更多背景信息。

相关内容