为什么当 nocasematch 关闭时,案例语句不区分大小写?



给定以下内容:

$ 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 不应该与 [a-z] 的小写字符类匹配,但它确实如此。为什么这场比赛没有失败?

您无法以这种方式可靠地使用破折号。 如果我不使用破折号,它会按预期工作:

$ 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的设置如何,它都会打印 TRUE。

Bash 在这里进行模式匹配。 查看参考手册的这一部分,其中说使用连字符可能会将[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 。对于后者,仅表示ab,而不是受排序顺序影响的范围。

如果将排序规则序列设置为区分大小写的序列,它将按预期工作:

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 )

最新更新