3

In a bash script, I wish to pass in a string which is contained in a variable, and contains up to 3 substrings separated by the '+' symbol. Each substring will have a specific numeric value, sort of like an octal mode.

I'd like to split the string into the substrings, convert them to their numeric value, and add the values together.

For instance if my substrings and values are:

  • hat = 1
  • shirt = 2
  • trousers = 4

And my variable containing these in a string is:

my_outfit=shirt+trousers

I'd like a variable called outfit_value to have a value of 6. How should I go about doing this?

I've thought about setting IFS to '+' and reading the variable into an array, then looping through the array and converting each element to its value. Unfortunately, my head turns to custard when I think about retrieving these numeric value elements and doing an arithmetic expression.

EDIT:

This is what I have so far, it seems to work, but I'd like to know if there are any problems, or if it could be done more safely/efficiently:

my_outfit=hat+shirt+trousers

oIFS=$IFS
IFS=+
read -a clothes <<< "$my_outfit"
IFS=$oIFS

outfit_value=0

for string in ${clothes[@]}
do
   if [[ $string = "hat" ]]
   then
      add_value=1
   elif [[ $string = "shirt" ]]
   then
      add_value=2
   elif [[ $string = "trousers" ]]
   then
      add_value=4
   fi
   let outfit_value="$outfit_value"+"$add_value"
done

echo "OUTFIT VALUE is $outfit_value"
  • 1
    So , how does an actual variable look like ? Where are corresponding values stored (array, other variables ) ? – Sergiy Kolodyazhnyy May 4 '16 at 12:45
  • @serg edited with my attempt! – Arronical May 4 '16 at 13:40
4

With bash, in an arithmetic evaluation context, variable names do not require the $ prefix. That means this is possible:

# set up the variables
hat=1 shirt=2 trousers=4
string="my_outfit=shirt+trousers"

# evaluate the equation 
(( $string ))

echo $my_outfit

outputs

6
  • 1
    Note, this is documented in the manual in the Shell Arithmetic section. See the first paragraph following the list of operators. – glenn jackman May 5 '16 at 15:34
2

Here's a variant of your original method, but using bash arrays. Note that there's no need to save an restore the field separator - you can simply assign a temporary value when you read the string

#!/bin/bash

# create a map (lookup table) from items to values
declare -A values=( [hat]=1 [shirt]=2 [trousers]=4 )
# (an ASSOCIATIVE array)

my_outfit='hat+shirt+trousers'

# convert the string to a simple (INDEXED) array
IFS=+ read -r -a my_items <<< "$my_outfit"

# loop over the array of items, looking up and summing the values 
outfit_value=0
for item in "${my_items[@]}"; do
  ((outfit_value += values[$item]))
done

printf 'OUTFIT VALUE is %s\n' "$outfit_value"
  • Thanks, this has helped improve my understanding of associative arrays, and has the bonus that I can do other operations on the elements in the my_items array during the for loop. – Arronical May 5 '16 at 8:13

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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