Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Case insensitive regex in Bash

I want to know which method is better to check if a var (input by user on keyboard) matches with a regex in a case insensitive way. I know there are some different possibilities. Example: I want a regex matching an empty value and all of this list: Y, N, y, n, Yes, No, YES, NO

I searched looking different methods. Not sure if could be another better. I'll put a couple of them working for me.

  • First one is a little "tricky" setting all to uppercase for the comparison:

    #!/bin/bash
    yesno="null" #any different value for initialization is valid
    while [[ ! ${yesno^^} =~ ^[YN]$|^YES$|^NO$|^$ ]]; do
        read -r yesno
    done
    
  • Second one is using shopt -s nocasematch. But not sure if after doing that it can be reverted because I don't want to set this for all the script.

    #!/bin/bash
    yesno="null" #any different value for initialization is valid
    shopt -s nocasematch
    while [[ ! ${yesno} =~ ^[yn]$|^yes$|^no$|^$ ]]; do
        read -r yesno
    done
    

Can these regex get improved in any way? Is there a better (more elegant) method? On second method, is there a way to revert that setting?

like image 386
OscarAkaElvis Avatar asked May 22 '17 07:05

OscarAkaElvis


People also ask

Is bash 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.


2 Answers

You can first convert the string into lowercase and check it. Then you don't need to touch nocasematch at all. The content of the variable is left unmodified as well.

#
# NOTE: This requires Bash 4.0+ (bash 4.0 was released on 2009-02-20)
#
# use the ${var,,} syntax to convert to lowercase
#
while [[ ! ${yesno,,} =~ ^(y|n|yes|no)$ ]]; do
    read -r -p "yes/no? " yesno
done
like image 119
pynexj Avatar answered Oct 16 '22 16:10

pynexj


shopt is good approach as you are able to retain originally entered value in variable yesno.

You can just refactor your regex a bit:

#!/bin/bash

yesno="null"

# set nocasematch option
shopt -s nocasematch

while [[ ! ${yesno} =~ ^([yn]|yes|no)?$ ]]; do
    read -r -p "Enter a yes/no value: " yesno
done

# unset nocasematch option
shopt -u nocasematch

# examine your variable
declare -p yesno
like image 38
anubhava Avatar answered Oct 16 '22 15:10

anubhava