user3470313
user3470313

Reputation: 323

bash: arithmetic expressions inside of variables

I have a simple code to assign variables in loop based on simple ariphmetic equaltion

 # assign initial value
    restr_start='25'
    # assign a new variable, which is a number that will decrease initial value by 5
    # keeping always the value of previous variable as restr_prev 
    for step in {1..4}; do
      let "restr=(${restr_start} - (5 * ${step}))"
      let "restr_prev=(${restr} + (5 * ${step}))"
      echo this is $restr current restart
      echo this is $restr_prev previous restart
    done

From this script I am expecting to have:

this is 20 current restart
this is 25 previous restart
this is 15 current restart
this is 20 previous restart
this is 10 current restart
this is 15 previous restart
this is 5 current restart
this is 10 previous restart

however what I actually do have

this is 20 current restart
this is 25 previous restart
this is 15 current restart
this is 25 previous restart
this is 10 current restart
this is 25 previous restart
this is 5 current restart
this is 25 previous restart

why $restr_prev is usually unchanged? how I could modify the code, e.g. using something instead of let?

Upvotes: 0

Views: 588

Answers (1)

Eduard Itrich
Eduard Itrich

Reputation: 866

This is rather a mathematical problem than an issue with your bash code. Look at the formula for $restr_prev:

restr_prev= ${restr} + (5 * ${step})

For step 1 the formula calculates to 20 + 5 * 1 = 25, for step 2 the formula leads to 15 + 5 * 2 = 25, and so on...

In order to get the results you're actually expecting, you simply need to add 5 to the restr value. Hence, the corresponding line in your script should look like this:

let "restr_prev=(${restr} + 5)"

As it was already suggested within the comments, you should use $((expression)) for arithmetic expansion instead of let since the latter is a bash builtin and not covered by the POSIX standard. Heeding the suggestions leads to the following code:

#!/bin/bash

# assign initial value
restr_start='25'
# assign a new variable, which is a number that will decrease initial value by 5
# keeping always the value of previous variable as restr_prev 
for step in {1..4}; do
    restr=$((restr_start - (5 * step)))
    restr_prev=$((restr + 5))
    echo "this is $restr current restart"
    echo "this is $restr_prev previous restart"
done

Upvotes: 2

Related Questions