5

I'm a newbie to bash scripting and trying to do some exercises. Getting error like this when I'm trying to stop the program with "finish" string.:

line 9: ((: finish: expression recursion level exceeded (error token is "finish").

What is the problem? Also I'd like to learn my other faults. My program is:

#!/bin/bash
number=0
finish="finish"
temp=0
echo "Enter a number."
while true;
do
    read -r number
    if (( $number > $temp ))
    then
        temp=$number
    fi
    if [[ $number == $finish ]]
    then 
       break
    fi
done    
echo "Largest : $temp"  
codeforester
  • 39,467
  • 16
  • 112
  • 140
Cemil Çakmak
  • 149
  • 1
  • 12

2 Answers2

4

To quote from @barmar's great answer to the related question, which talks about the same issue that @GordonDavisson mentions in his comment:

When you use a variable in an arithmetic expression, but the value is not a number, the shell treats it as another expression to evaluate. So if the value is a variable name, it will get the value of that variable and use it. But in this case, you have it pointing to itself. So to evaluate a it has to evaluate $finish, and this keeps repeating infinitely.


The simplest solution is to use a different name to your variable - say finish_string="finish" instead of finish="finish".

Also, you can use a regex match to see if the value is numeric (note: a dollar sign is not needed to expand variables inside arithmetic expression ((...))), then do the numeric comparison followed by the normal string comparison to see if the value is 'finish':

if [[ $number =~ ^[0-9]+$ ]] && ((number > temp)); then
  temp=$number
elif [[ $number == $finish ]]; then
  break
fi

Or, you could explicitly check if the user entered a number before doing a numeric comparison:

if [[ $number == $finish ]]; then
  break
else
  [[ $number =~ ^[0-9]+$ ]] || { echo "Enter a valid number or 'finish' to stop"; continue; }
  if ((number > temp)); then
    temp=$number
  fi
fi

Run your script with bash -x yourscript.sh to debug it.


Related:

See also:

codeforester
  • 39,467
  • 16
  • 112
  • 140
  • 1
    More specifically: the original problem was that when it sees `$number` inside the arithmetic expression, it expands it to the value of the variable: "finish". That's not a number, so it does what it always does with non-numbers in an expression: assumes they're inplicitly-referenced variables and expands them. In this case, expanding `finish` as a variable yields "finish", which isn't a number either, so it tries to expand it as a variable... etc etc etc until it decides it's tried long enough and gives up. – Gordon Davisson Oct 11 '18 at 06:37
  • Amazing explanation @GordonDavisson. I wasn't aware of this issue. – codeforester Oct 11 '18 at 06:44
  • @codeforester Thanks for the answer, I got the idea. However in the 1st solution, the temp variable does not change after I assign an integer to number variable. The solution that program gives always 0, in the 2nd solution it gives the same error with mine. – Cemil Çakmak Oct 11 '18 at 10:10
  • My regex pattern was wrong and that's the reason the code didn't do what it was supposed to do. I have fixed the issue now. – codeforester Oct 11 '18 at 16:56
0

"finish" is not a number but you are comparing it with a number.To solve your immediate problem, check for "finish" before doing the comparison:

while true;
do
    read -r number
    if [[ $number == $finish ]] ## this line moved up
    then 
       break
    fi
    if (( $number > $temp ))
    then
        temp=$number
    fi
done 

Of course, you still have the problem that even if $number != "finish", it might still not be a number, but that was not the question...

Tano Fotang
  • 449
  • 3
  • 7
  • This will work well, though not very elegant. Arithmetic expression evaluates to false if the variables used inside `((...))` expand to non-numeric values. – codeforester Oct 11 '18 at 06:56
  • @codeforester your're correct, of course. However, not checking for input validity, appears to be a different bug than the one the question was about. Addressing that issue, we might end up writing his code for him... – Tano Fotang Oct 11 '18 at 07:03