0

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?

5
  • The math looks right! what is your question? Commented Jun 20, 2019 at 10:09
  • @Inian No, the formula for restr_prev isn't correct. Please have a look at my answer for a more precise explanation. Commented Jun 20, 2019 at 10:14
  • @EduardItrich: I meant that for the code OP had the output it produced was right. For a different output, the code needs to be changed Commented Jun 20, 2019 at 10:15
  • Don't use let; it's obsolete in the presence of POSIX arithmetic expressions. restr=$((restr_start - 5*step)). Commented Jun 20, 2019 at 11:27
  • Or even better (but not POSIX): (( restr = restr_start - 5 * step )) - note in both these examples that the dollar signs and curly braces are omitted from the variable names. Commented Jun 20, 2019 at 12:03

1 Answer 1

2

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
Sign up to request clarification or add additional context in comments.

3 Comments

See chepner's and my comments on the question regarding arithmetic formulas. Always quote your variables (the echo commands, for example).
why restr_prev=$((restr + 5)) is better than let "restr_prev=(${restr} + 5)" ?
Please have a look at my revised answer, which addresses your question.

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.