How do I change the case (upper and lower case) of strings in my variable?

5,950

Solution 1

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

Solution 2

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).

Solution 3

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

Solution 4

sed -ne '/^[aA]$/!i\' -e failed -e 's//worked/p;q' </dev/tty
Share:
5,950

Related videos on Youtube

Zac
Author by

Zac

Updated on September 18, 2022

Comments

  • Zac
    Zac over 1 year
    "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?

    • Admin
      Admin over 9 years
      Which shell? bash?
  • muru
    muru over 9 years
    An extension of (2): [[ "${test,,}" == "a" ]].
  • Costas
    Costas over 9 years
    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.
  • Stéphane Chazelas
    Stéphane Chazelas over 9 years
    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}"'
  • PM 2Ring
    PM 2Ring over 9 years
    @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. :(
  • Stéphane Chazelas
    Stéphane Chazelas over 9 years
    It's not only Turkish locales. I've just reported it as a bash bug.
  • Stéphane Chazelas
    Stéphane Chazelas over 9 years
    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.
  • Hauke Laging
    Hauke Laging over 9 years
    @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.
  • PM 2Ring
    PM 2Ring over 9 years
    @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.