Bash Regex match is case insensitive

Viewed 950

Trying to match a string to only contain lowercase, digit or hypen (-). I had some problems with it and tried to debug my regex. Meanwhile I found that the following matches, even though it shouldn't:

$ if [[ "ABC" =~ ^[a-z]+$ ]]; then echo matched; fi
> matched
$ if [[ "ABC" =~ ^[[:lower:]]+$ ]]; then echo matched; fi
> matched

$ if [[ "abc" =~ ^[a-z]+$ ]]; then echo matched; fi
> matched
$ if [[ "abc" =~ ^[[:lower:]]+$ ]]; then echo matched; fi
> matched

$ echo $LC_CTYPE
> en_US.utf8
$ locale
LANG=de_DE.utf8
LANGUAGE=
LC_CTYPE=en_US.utf8
LC_NUMERIC=en_US.utf8
LC_TIME=de_DE.utf8
LC_COLLATE="de_DE.utf8"
LC_MONETARY=de_DE.utf8
LC_MESSAGES=POSIX
LC_PAPER=de_DE.utf8
LC_NAME=en_US.utf8
LC_ADDRESS=de_DE.utf8
LC_TELEPHONE=de_DE.utf8
LC_MEASUREMENT=de_DE.utf8
LC_IDENTIFICATION=de_DE.UTF-8
LC_ALL=

$ echo $LC_COLLATE # Gives empty line

$ shopt nocasematch
off

I'm using ubuntu 18.04 with glibc version 2.27-3ubuntu1 So I'm kinda lost here. Why does this match?

2 Answers

Ok, found it. The reason was that nocaseglob was set.

Also dug a bit into the source code:

nocaseglob is defined in ./builtins/shopt.def which sets the internal variable glob_ignore_case.

This one in return is used in ./lib/sh/shmatch.c in the if-statement if (glob_ignore_case || match_ignore_case) which determines if the flag REG_ICASE should be set for the call to regcomp.

But according to the documentation on shopt nocaseglob only determines if filenames are match case-insensitiv, while I expected nocasematch to be responsible for regex-matching:

nocaseglob: If set, Bash matches filenames in a case-insensitive fashion when performing filename expansion.

nocasematch: If set, Bash matches patterns in a case-insensitive fashion when performing matching while executing case or [[ conditional commands, when performing pattern substitution word expansions, or when filtering possible completions as part of programmable completion.


Tracked to at least bash-3.0 which introduced the file shmatch.c to the current master version 5.0.17(2)-release. Fixed in devel branch 5.1.0(3)-alpha by commit aa99ef520 with the changelog

lib/sh/shmatch.c - sh_regmatch: implement a suggestion from Grisha Levit and don't allow nocaseglob to enable case-insensitive regexp matching. It hasn't been documented that way in years

Try shopt -u nocasematch and see if that helps.

Related