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
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.)
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 man
bash`:
${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.
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