Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Case insensitive comparision in If condition

Tags:

bash

shell

I have this csv file and i need to count the number of rows which satisfies the condition that the row entry is betwen a certain year range and the artist_name matches the name argument. But the string matching should be case insensitive. How do i achieve that in the if loop..

I am a beginner, so please bear with me

#!/bin/bash

file="$1"
artist="$2" 
from_year="$(($3-1))"
to_year="$(($4+1))"
count=0

while IFS="," read arr1 arr2 arr3 arr4 arr5 arr6 arr7 arr8 arr9 arr10 arr11 ; do

if [[ $arr11 -gt $from_year ]] && [[ $arr11 -lt $to_year ]] && [[ $arr7  =~ $artist ]]; then
count=$((count+1))
fi

done < "$file"
echo $count

The $arr7 =~ $artist part is where i need to make the modification

like image 886
Sparshith Puttaswamy Gowda Avatar asked Oct 12 '14 00:10

Sparshith Puttaswamy Gowda


3 Answers

Bash has a builtin method for converting strings to lower case. Once they are both lower case, you can compare them for equality. For example:

$ arr7="Rolling Stones"
$ artist="rolling stoneS"
$ [ "${arr7,,}" = "${artist,,}" ] && echo "Matches!"
Matches!
$ [[ ${arr7,,} =~ ${artist,,} ]] && echo "Matches!"
Matches!

Details

${parameter,,} converts all characters in a string to lower case. If you wanted to convert to upper case, use ${parameter^^}. If you want to convert just some of the characters, use ${parameter,,pattern} where only those characters matching pattern are changed. Still more details on this are documented by manbash`:

${parameter^pattern}
${parameter^^pattern}
${parameter,pattern}
${parameter,,pattern}

Case modification. This expansion modifies the case of alphabetic characters in parameter. The pattern is expanded to produce a pattern just as in pathname expansion. The ^ operator converts lowercase letters matching pattern to uppercase; the , operator converts matching uppercase letters to lowercase. The ^^ and ,, expansions convert each matched character in the expanded value; the ^ and , expansions match and convert only the first character in the expanded value. If pattern is omitted, it is treated like a ?, which matches every character. If parameter is @ or *, the case modification operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the case modification operation is applied to each member of the array in turn, and the expansion is the resultant list.

Compatibility

These case modification methods require bash version 4 (released on 2009-Feb-20) or better.

like image 184
John1024 Avatar answered Oct 15 '22 05:10

John1024


The bash case-transformations (${var,,} and ${var^^}) were introduced (some time ago) in bash version 4. However, if you are using Mac OS X, you most likely have bash v3.2 which doesn't implement case-transformation natively.

In that case, you can do lower-cased comparison less efficiently and with a lot more typing using tr:

if [[ $(tr "[:upper:]" "[:lower:]" <<<"$arr7") = $(tr "[:upper:]" "[:lower:]" <<<"$artist") ]]; then
  # ...
fi

By the way, =~ does a regular expression comparison, not a string comparison. You almost certainly wanted =. Also, instead of [[ $x -lt $y ]] you can use an arithmetic compound command: (( x < y )). (In arithmetic expansions, it is not necessary to use $ to indicate variables.)

like image 26
rici Avatar answered Oct 15 '22 07:10

rici


Use shopt -s nocasematch

demo

#!/bin/bash

words=(Cat dog mouse cattle scatter)


#Print words from list that match pat
print_matches()
{
    pat=$1
    echo "Pattern to match is '$pat'"
    for w in "${words[@]}"
    do
        [[ $w =~ $pat ]] &&  echo "$w"
    done
    echo
}

echo -e "Wordlist: (${words[@]})\n"

echo "Normal matching"
print_matches 'cat'
print_matches 'Cat'

echo -e "-------------------\n"

echo "Case-insensitive matching"
shopt -s nocasematch

print_matches 'cat'
print_matches 'CAT'

echo -e "-------------------\n"

echo "Back to normal matching"
shopt -u nocasematch

print_matches 'cat'

output

Wordlist: (Cat dog mouse cattle scatter)

Normal matching
Pattern to match is 'cat'
cattle
scatter

Pattern to match is 'Cat'
Cat

-------------------

Case-insensitive matching
Pattern to match is 'cat'
Cat
cattle
scatter

Pattern to match is 'CAT'
Cat
cattle
scatter

-------------------

Back to normal matching
Pattern to match is 'cat'
cattle
scatter
like image 40
PM 2Ring Avatar answered Oct 15 '22 07:10

PM 2Ring