One problem with using the truncate operator for string matching is case matching.
In the truncate operator example, ${foo%%*ATE}
matches SENATE.
DALEK$ foo=SENATE
DALEK$ if [ '' = "${foo%%*ATE}" ] ; then echo "$foo! $foo!"; fi
SENATE! SENATE!
DALEK$
It will not match Senate
because ate
and ATE
are different cases.
DALEK$ foo=Senate
DALEK$ if [ '' = "${foo%%*ATE}" ] ; then echo "$foo! $foo!"; fi
DALEK$
It will match SenATE
because ATE
and ATE
match.
DALEK$ foo=SenATE
DALEK$ if [ '' = "${foo%%*ATE}" ] ; then echo "$foo! $foo!"; fi
SenATE! SenATE!
DALEK$
The pattern substitution operator can match in a case insensitive way such that lower case letters also match upper case letters and vice versa.
By default, it is case sensitive like the truncate operator.
DALEK$ foo=SENATE
if [ '' = "${foo/*ATE/}" ] ; then echo "$foo! $foo!"; fi
SENATE! SENATE!
DALEK$ foo=Senate
if [ '' = "${foo/*ATE/}" ] ; then echo "$foo! $foo!"; fi
DALEK$
The nocasematch
shell option disables case sensitivity for some operations. It affects the pattern substitution string operator, but does not affect the truncate string operator. It defaults to off.
DALEK$ shopt nocasematch
nocasematch off
DALEK$
Enabling nocasematch
allows the pattern substitution string operator patterns to match both lower case and upper case letters.
Because nocasematch
can impact other shell behavior the remaining examples will use subshells.
Putting an opening parenthesis in front of the commands and a closing parenthesis behind them runs them in a subshell. The key feature in this case is that changes made in the subshell do not change the parent shell.
Also, comments on the command line start with an unquoted hash.
DALEK$ foo=SENATE
DALEK$ echo $foo
SENATE
DALEK$ # This line is a comment.
DALEK$ # The next line sets foo in a subshell then displays the value of foo in it
DALEK$ ( foo=Senate; echo $foo )
Senate
DALEK$ echo $foo
SENATE
DALEK$
The first and last echo
commands take place in the parent shell and show that the value of foo
didn't change.
The -s
option to shopt
sets a value.
DALEK$ ( shopt nocasematch; shopt -s nocasematch; shopt nocasematch )
nocasematch off
nocasematch on
DALEK$
Now, let's use nocasematch
to do some case insensitive matching.
DALEK$ ( shopt -s nocasematch
> foo=Senate
> if [ '' = "${foo/*ATE}" ] ; then
> echo "$foo! $foo!"
> fi )
Senate! Senate!
DALEK$
The following demonstrates that the pattern will match both lower case and upper case letters by using both in the string to be matched.
DALEK$ ( shopt -s nocasematch
> foo=AlTeRnAtE
> if [ '' = "${foo/*ATE}" ] ; then
> echo "$foo! $foo!"
> fi )
AlTeRnAtE! AlTeRnAtE!
DALEK$
If you write a shell script using the pattern substitution operator that depends on case sensitive behavior you should verify the status of nocasematch
before using it.
Like with truncate, pattern matching can match the middle of the string as well.
LIGHTNING$ ( shopt -s nocasematch
> foo=BICARBONATE
> if [ '' = "${foo/*car*}" ] ; then
> echo "$foo can be pixarified."
> fi )
BICARBONATE can be pixarified.
LIGHTNING$
As mentioned above, nocasematch
does not affect behavior of the truncate operator.
DALEK$ ( shopt -s nocasematch
> shopt nocasematch
> foo=Senate
> if [ '' = "${foo%%*ATE}" ] ; then
> echo "$foo! $foo!"
> else
> echo "nope, not here"
> fi )
nocasematch on
nope, not here
DALEK$
Happy globbing!
Comments
July 24, 2023 08:32
I am really impressed with your article. The information you share will be an important document for me to learn more about this topic. mapquest directions california
December 29, 2023 08:49
I stumbled upon your website. It is extraordinary and intriguing. I must concede that this composition of yours was slope phenomenal. Your provision of this invaluable information is greatly appreciated.