我在 Bash 中做了一些正则表达式检查,以确保字符串只包含正常的字符,但我遇到了这种奇怪的行为。
在
grep
中看起来是一样的。
我做错了什么还是一个错误? 如果是错误,到哪里报告?
小写字母
š
被错误地检测为 a-z
: 之间的字符
[[ 'š' =~ ^[a-z]$ ]] && echo sane || echo nope
sane
[[ 'š' =~ [a-z] ]] && echo sane || echo nope
sane
grep '^[a-z]$' <<<'š' && echo sane || echo nope
š
sane
小写字母
ž
被正确检测为不是 a-z
: 之间的字符
[[ 'ž' =~ ^[a-z]$ ]] && echo sane || echo nope
nope
[[ 'ž' =~ [a-z] ]] && echo sane || echo nope
nope
grep '^[a-z]$' <<<'ž' && echo sane || echo nope
nope
大写
Š
被正确检测为不是 a-z
: 之间的字符
[[ 'Š' =~ ^[a-z]$ ]] && echo sane || echo nope
nope
[[ 'Š' =~ [a-z] ]] && echo sane || echo nope
nope
grep '^[a-z]$' <<<'Š' && echo sane || echo nope
nope
大写
Š
被错误地检测为A-Z
:之间的字符
[[ 'Š' =~ ^[A-Z]$ ]] && echo sane || echo nope
sane
[[ 'Š' =~ [A-Z] ]] && echo sane || echo nope
sane
grep '^[A-Z]$' <<<'Š' && echo sane || echo nope
Š
sane
我的 Bash 版本:
GNU bash, version 5.1.8(1)-release (x86_64-redhat-linux-gnu)
我的 grep 版本:
grep (GNU grep) 3.6
我的所在地:
locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
不要使用范围;使用字符类,其行为将独立于代码点排序而正确。例如,在我的机器上,
bash-5.0$ [[ 'š' =~ ^[a-z]$ ]] && echo sane || echo nope
nope
bash-5.0$ [[ 'š' =~ ^[[:lower:]]$ ]] && echo sane || echo nope
sane
(我怀疑它在 5.1 中的表现有所不同;我在 3.2 和 4.4 中也得到了相同的结果。)