鉴于以下情况:
$ echo $BASH_VERSION
4.2.10(1)-release
$ shopt | fgrep case
nocaseglob off
nocasematch off
$ case A in [a-z]) echo TRUE;; esac
TRUE
我希望大写字母A不应该与[az]的小写字符类匹配,但确实如此。为什么这场比赛没有失败?
鉴于以下情况:
$ echo $BASH_VERSION
4.2.10(1)-release
$ shopt | fgrep case
nocaseglob off
nocasematch off
$ case A in [a-z]) echo TRUE;; esac
TRUE
我希望大写字母A不应该与[az]的小写字符类匹配,但确实如此。为什么这场比赛没有失败?
您不能以这种方式可靠地使用破折号。如果我不使用破折号,它会按预期工作:
$ bash --version
GNU bash, version 4.2.10(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ shopt -s nocasematch
$ case A in [abc]) echo TRUE;; esac
TRUE
$ shopt -u nocasematch
$ case A in [abc]) echo TRUE;; esac
$
但是使用破折号,无论nocasematch
.
Bash 在这里进行模式匹配。查看参考手册的这一部分,其中说使用连字符 MIGHT 解释[a-z]
为[A-Za-z]
! 它告诉您如何获得传统解释(将 LC_COLLATE 或 LC_ALL 设置为 C)。基本上,您的默认语言环境是按字典顺序排序的。参考手册很好地解释了事情。
附录
好的,我有一份成绩单给你。
$ shopt -u nocasematch
$ case A in [a-z]) echo TRUE;; esac
TRUE
$ shopt -s nocasematch
$ case A in [a-z]) echo TRUE;; esac
TRUE
$ LC_ALL=C
$ shopt -u nocasematch
$ case A in [a-z]) echo TRUE;; esac
$ shopt -s nocasematch
$ case A in [a-z]) echo TRUE;; esac
TRUE
它与您的语言环境设置有关。具体来说,整理顺序是不区分大小写的。
例如,LC_COLLATE
设置为en_AU.utf8
(我系统上的默认设置),您可以看到它包括小写和大写:
pax> case A in [a-b]) echo TRUE;; esac
TRUE
pax> _
但是,如果你去掉范围说明符,它会按预期工作:
pax> case A in [ab]) echo TRUE;; esac
pax> _
那是因为between a and b inclusive
对于该整理序列,第一个意味着包含A
. 对于后一种方式a
,并且b
仅适用于不受整理顺序影响的范围。
如果您将整理顺序设置为区分大小写的顺序,它将按预期工作:
pax> export LC_COLLATE="C"
pax> case A in [a-b]) echo TRUE;; esac
pax>
如果您只想将其作为一次性操作执行而不影响其他任何操作,则可以在子 shell 中执行此操作:
( export LC_COLLATE="C" ; case A in [a-b]) echo TRUE;; esac )