我在 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,终端是lxterminal
并echo $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
了解更多背景信息。