4

I'm trying to use bash to find if a short string is present in any string "sets". For example,

FRUIT="apple banana kiwi melon"
VEGETABLE="radish lettuce potato"
COLOR="blue red yellow green brown"

MY_CHOICE="kiwi"
MY_CHOICE_GROUP="?"

How can I set MY_CHOICE_GROUP to FRUIT?

I tried to use this StackOverflow solution, but it only works with a single string set.

Originally, I was using arrays to store the options in a set, but given the way bash handles iteration over arrays, it seems a string search would be more efficient.

Many thanks!

2
  • Are the sets 'given' (unchanging)? Commented Jul 17, 2013 at 22:23
  • Yes, they are given (they won't change). Commented Jul 17, 2013 at 22:24

3 Answers 3

6
  1. The simplest way, IMO, would be to just hardcode a bunch of case...esac labels.

    #!/bin/bash
    function lookup()
    {
        case "$1" in
            apple|banana|kiwi|melon)
                echo "FRUIT"
                ;;
    
            radish|lettuce|potato)  
                echo "VEGETABLE"
                ;;
    
            blue|red|yellow|green|brown)   
                echo "COLOR"
                ;;
        esac
    }
    
    MY_CHOICE="kiwi"
    MY_CHOICE_GROUP=$(lookup "$MY_CHOICE")
    
    echo $MY_CHOICE: $MY_CHOICE_GROUP
    

    See it live on ideone

  2. Otherwise, consider associative arrays, see it live on ideone:

    #!/bin/bash
    declare -A groups
    
    groups["apple"]="FRUIT"
    groups["banana"]="FRUIT"
    groups["kiwi"]="FRUIT"
    groups["melon"]="FRUIT"
    
    groups["radish"]="VEGETABLE"
    groups["lettuce"]="VEGETABLE"
    groups["potato"]="VEGETABLE"
    
    groups["blue"]="COLOR"
    groups["red"]="COLOR"
    groups["yellow"]="COLOR"
    groups["green"]="COLOR"
    groups["brown"]="COLOR"
    
    MY_CHOICE="kiwi"
    MY_CHOICE_GROUP=${groups[$MY_CHOICE]}
    
    echo $MY_CHOICE: $MY_CHOICE_GROUP
    
Sign up to request clarification or add additional context in comments.

1 Comment

+1 for two solutions, though would be nice to mention that second one is bash version 4 or later only.
1

Only shortening a bit @sehe's answer:

#!/bin/bash

declare -A groups
mkaso() { val="$1"; shift; for key in "$@"; do groups["$key"]="$val"; done; }

mkaso FRUIT apple banana kiwi melon
mkaso VEGETABLE radish lettuce potato
mkaso COLOR blue red yellow green brown
#declare -p groups

MY_CHOICE="kiwi"
MY_CHOICE_GROUP=${groups[$MY_CHOICE]}
echo $MY_CHOICE: $MY_CHOICE_GROUP

Comments

1
#!/bin/bash
FRUIT="apple banana kiwi melon"
VEGETABLE="radish lettuce potato"
COLOR="blue red yellow green brown"

MY_CHOICE="kiwi"

for group in VEGETABLE COLOR FRUIT
do
    if [[ ${!group} == *${MY_CHOICE}* ]]; then
        MY_CHOICE_GROUP=$group
        break
    fi
done

echo $MY_CHOICE_GROUP

1 Comment

+1 for using variable indirection, but finish the job in bash: if [[ ${!group} == *${MY_CHOICE}* ]]; ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.