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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10695029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 02:21:19  来源:igfitidea点击:

Why isn't the case statement case-sensitive when nocasematch is off?

bashpattern-matching

提问by Todd A. Jacobs

Given the following:

鉴于以下情况:

$ echo $BASH_VERSION
4.2.10(1)-release

$ shopt | fgrep case
nocaseglob      off
nocasematch     off

$ case A in [a-z]) echo TRUE;; esac
TRUE

I expect that the capital letter Ashould notmatch the lower-case character class of [a-z], but it does. Why doesn't this match fail?

我想到的是,大写字母一个应该匹配小写字符类[AZ] ,但它确实。为什么这场比赛没有失败?

回答by Ray Toal

You can't reliably use the dash this way. If I don't use dashes, it works as expected:

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

$ 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
$ 

But withdashes, it prints TRUE regardless of the setting of nocasematch.

但是对于破折号,无论nocasematch.

Bash is doing pattern matching here. Check out this section of the reference manualwhere it says that using the hyphen MIGHT interpret [a-z]as [A-Za-z]! It tells you how to get the traditional interpretation (set LC_COLLATE or LC_ALL to C). Basically your default locale is sorting in dictionary order. The reference manual explains things pretty well.

Bash 在这里进行模式匹配。查看参考手册的这一部分,其中说使用连字符可能会解释[a-z][A-Za-z]! 它告诉您如何获得传统解释(将 LC_COLLATE 或 LC_ALL 设置为 C)。基本上,您的默认语言环境是按字典顺序排序的。参考手册很好地解释了事情。

ADDENDUM

附录

Okay I have a transcript for you.

好的,我有一个成绩单给你。

$ 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

回答by paxdiablo

It has to do with your locale settings. Specifically, the collating sequence is one with case-insensitivity.

这与您的语言环境设置有关。具体来说,整理顺序是一种不区分大小写的顺序。

For example, with LC_COLLATEset to en_AU.utf8(the default on my system), you can see that it includes lowercase and uppercase together:

例如,LC_COLLATE设置为en_AU.utf8(我系统上的默认值),您可以看到它包括小写和大写:

pax> case A in [a-b]) echo TRUE;; esac
TRUE
pax> _

but, if you get rid of the range specifier, it works as expected:

但是,如果你去掉范围说明符,它会按预期工作:

pax> case A in [ab]) echo TRUE;; esac
pax> _

That's because the first means between a and b inclusivewhich, for that collating sequence, includes A. For the latter means aand bonly, not a range that would be affected by the collating sequence.

那是因为第一个意味着between a and b inclusive,对于该整理序列,包括A. 对于后者ab仅表示不会受整理顺序影响的范围。

If you set your collating sequence to a case-sensitive one, it works as you expect:

如果您将整理序列设置为区分大小写的序列,它将按您的预期工作:

pax> export LC_COLLATE="C"
pax> case A in [a-b]) echo TRUE;; esac
pax> 

If you just want to do this as a one-off operation without affecting anything else, you can do it in a sub-shell:

如果您只想将其作为一次性操作执行而不影响其他任何操作,您可以在子 shell 中执行此操作:

( export LC_COLLATE="C" ; case A in [a-b]) echo TRUE;; esac )