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) – echo $BASH_VERSION

编辑: 安德鲁约翰逊在他的评论中表示,使用gnome-terminal 4.2.37(1) – 发布命令工作正常。 我想知道这是lxterminal还是其特定的4.2.24(1) – 发布版本的问题。

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

简短回答:

设置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实现。 除了C语言环境之外,POSIX标准使其特别未定义。 (Bash为此调用了一个外部库,并且,如果只有ASCII字符存在,它看起来会回到ASCII排序)。

更高版本的bash有一个shell选项,可以让你指定你期望的东西。

看到:

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

了解更多背景资料