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 A should not match the lower-case character class of [a-z], but it does. Why doesn't this match fail?
The switch statement compares the String object in its expression with the expressions associated with each case label as if it were using the String. equals method; consequently, the comparison of String objects in switch statements is case sensitive.
Variables in Bash Scripts are untyped and declared on definition. Bash also supports some basic type declaration using the declare option, and bash variables are case sensitive.
Java switch case String is case sensitive, the output of example confirms it. Java Switch case uses String. equals() method to compare the passed value with case values, so make sure to add a NULL check to avoid NullPointerException.
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 with dashes, it prints TRUE regardless of the setting of nocasematch
.
Bash is doing pattern matching here. Check out this section of the reference manual where 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.
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
It has to do with your locale settings. Specifically, the collating sequence is one with case-insensitivity.
For example, with LC_COLLATE
set to en_AU.utf8
(the default on my system), you can see that it includes lowercase and uppercase together:
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 inclusive
which, for that collating sequence, includes A
. For the latter means a
and b
only, not a range that would be affected by the collating sequence.
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:
( export LC_COLLATE="C" ; case A in [a-b]) echo TRUE;; esac )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With