1
"Enter test: "
read test

if [[ $test == "a" ]]; then
    echo "worked"
else
    echo "failed"
fi

It's a simple illustration of test I'm doing, but if I enter "A", it will fail. Is there anything I can do at the variable stage to change it all to small case, so that the test will match?

  • 5
    Which shell? bash? – Hauke Laging Jan 22 '15 at 13:21
5

There are several useful ways to achieve this (in bash):

two checks

echo -n "Enter test: "
read test

if [[ $test == "a" || $test == "A" ]]; then
    echo "worked"
else
    echo "failed"
fi

make the input lower case

echo -n "Enter test: "
read test
test="${test,,}"

if [[ $test == "a" ]]; then
    echo "worked"
else
    echo "failed"
fi

regex for both cases

echo -n "Enter test: "
read test

if [[ $test =~ ^[aA]$ ]]; then
    echo "worked"
else
    echo "failed"
fi

make the shell ignore the case

echo -n "Enter test: "
read test

shopt -s nocasematch
if [[ $test == a ]]; then
    echo "worked"
else
    echo "failed"
fi
  • 2
    An extension of (2): [[ "${test,,}" == "a" ]]. – muru Jan 22 '15 at 13:31
  • As =~ is match operator you can use [[ Aa =~ "$test" ]]. And so if [[ (bash keyword) is used instead of posix test so [[ "$test" == [Aa] ]] is acceptable too. – Costas Jan 22 '15 at 13:48
  • @Costas [[ Aa =~ "$test" ]] doesn't make sense. That matches even . as input. Even if the reversal of string and pattern may work sometimes that is certainly not a good idea. – Hauke Laging Jan 22 '15 at 15:09
7

Just use the standard sh (POSIX and Bourne) syntax:

case $answer in
  a|A) echo OK;;
  *)   echo >&2 KO;;
esac

Or:

case $answer in
  [aA]) echo OK;;
  *)    echo >&2 KO;;
esac

With bash, ksh or zsh (the 3 shells that support that non-standard [[...]] syntax), you can declare a lower case variable:

typeset -l test
printf 'Enter test: '
read test
if [ "$test" = a ]; then...

(beware that bash's case conversion is bogus in some locales).

2

There are several ways to do this. If you're using a recent version of bash it's quite easy: you can convert the case of test, or you can use a regex to match both upper & lower case a.

First the regex way:

read -p "enter test: " test;[[ $test =~ ^[Aa]$ ]] && echo yes || echo no

Now the case shifter:

read -p "enter test: " test;[[ ${test^^} = A ]] && echo yes || echo no
  • Note that bash's case conversion doesn't work in all locales. See a=i LC_ALL=tr_TR.UTF-8 bash -c 'echo "${a^^}"' which gives i instead of the expected İ (not I) like a=i LC_ALL=tr_TR.UTF-8 zsh -c 'echo "${(U)a}"' – Stéphane Chazelas Jan 22 '15 at 14:02
  • @StéphaneChazelas: How annoying! Thanks for that info, Stéphane. Unfortunately, I can't test that example as I don't have that locale (Turkish?) on my system. FWIW, I don't know much about locales, but yesterday I was trying to find an equivalent in Python of locale -k LC_IDENTIFICATION ... to no avail. :( – PM 2Ring Jan 22 '15 at 14:08
  • It's not only Turkish locales. I've just reported it as a bash bug. – Stéphane Chazelas Jan 22 '15 at 14:45
  • about your locale -k, look at info libc 'The Elegant and Fast Way' (especially about the additional symbols in langinfo.h). Those are non-portable, subject to change GNU extensions. – Stéphane Chazelas Jan 22 '15 at 14:58
  • @StéphaneChazelas: I see. The file langinfo.h defines a lot more symbols but none of them is official. Using them is not portable, and the format of the return values might change. Therefore we recommended you not use them. No wonder Python doesn't give me access to that info. Oh well. I just wanted an equivalent of LANG="$name" locale -k LC_IDENTIFICATION | grep -E '^(title|language|territory|ident)' which is a handy way to verify that a locale refers to the language that you think it does. IMHO. – PM 2Ring Jan 23 '15 at 8:30
1
sed -ne '/^[aA]$/!i\' -e failed -e 's//worked/p;q' </dev/tty

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.