-4

I have been given this test question:

In the output, in the following lines, write the next terms of the Fibonacci sequence from the first to the nth term inclusive. We assume that the first and second terms of the Fibonnaci sequence are 0 and 1.

I copied shell code to generate the Fibonacci sequence (from here), I just need to have the condition 1<=n<=50 and I can't understand how to add this after the while loop:

function fib
{
  x=0
  y=1
  i=2
  echo "Fibonacci Series up to $n terms :"
  echo "$x"
  echo "$y"
  while [ $i -lt $n ]
  do
      i=`expr $i + 1 `
      z=`expr $x + $y `
      echo "$z"
      x=$y
      y=$z
  done
}
r=`fib $n`
echo "$r"
Kusalananda
  • 333,661
  • please remove all the extra whitespace you added to your code. Instead, select your code and click on the "Code formatting" button (It's labeled {} and is above your question editor)! – Marcus Müller Apr 08 '23 at 13:39
  • What should happen if n > 50? Should it exit? Print an error? Return the result for until the largest value of n which is still < 50? And Where is n defined? – terdon Apr 08 '23 at 13:56
  • yes when get input more than 50 than must be EXIT, for example: inpute 5 than output = 0 1 1 2 3 – Shafi Faizi Apr 08 '23 at 14:02
  • 1
    Advice to newcomers: If an answer solves your problem, please accept it by clicking the large check mark (✓) next to it and optionally also up-vote it (up-voting requires at least 15 reputation points). If you found other answers helpful, please up-vote them. Accepting and up-voting helps future readers. – Gilles Quénot Apr 12 '23 at 20:13

3 Answers3

0

You can do this before your loop to abort the function:

if [[ $n -lt 1 ]] || [[ $n -gt 50 ]]
then
    return
fi

You can also cap the input value like this:

if [[ $n -lt 1 ]]
then
    n=1
fi
if [[ $n -gt 50 ]]
then
    n=50
fi

Here a working version of your code with the first option:

function fib
{
  x=0
  y=1
  i=2
  n=$1

if [[ $n -lt 1 ]] || [[ $n -gt 50 ]] then return fi

echo "Fibonacci Series up to $n terms :" echo "$x" echo "$y" while [[ $i -lt $n ]] do i=expr $i + 1 z=expr $x + $y echo "$z" x=$y y=$z done } r=fib $n echo "$r"

0

In modern shell, avoiding old deprecated mathematical syntax and backticks, enhance readability:

#!/bin/bash

fib(){

x=0 y=1 i=2 n=$1

((n &lt; 1 || n &gt; 50)) &amp;&amp; return

echo &quot;Fibonacci Series up to $n terms :&quot;
echo &quot;$x&quot;
echo &quot;$y&quot;
while ((i++ &lt; n)); do
    z=$((x+y))
    echo &quot;$z&quot;
    x=$y y=$z
done

}

read -p 'Type an integer between 1 and 50 as max terms >>> ' n r=$(fib $n) echo "$r"

((...)) and $((...)) are arithmetic commands, which returns an exit status of 0 if the expression is nonzero, or 1 if the expression is zero. Also used as a synonym for "let", if side effects (assignments) are needed. See http://mywiki.wooledge.org/ArithmeticExpression.


The backquote is used in the old-style command substitution. The foo=$(command) syntax is recommended instead. Backslash handling inside $() is less surprising, and $() is easier to nest. See http://mywiki.wooledge.org/BashFAQ/082


expr is a program used in ancient shell code to do math. In Posix shells like bash, use $(( expression )). In bash, ksh, mksh, pdksh, yash, dash, ash, sh or zsh, you can also use (( expression ))

0

Beware that, in bash and other Korn-like shells, using unsanitised data inside of arithmetic expressions which includes Korn-style ((...)) and $((...)) and arguments to arithmetic operators inside the [[...]] construct introduces an arbitrary command execution vulnerability.

expr is generally not usable reliably and has been obsolete for a few decades.

So you should sanitise the input to make sure it is a valid number in the format you expect, before using it in any arithmetic context.

In bash arithmetic expressions, numbers with leading zeros are interpreted as octal, so it's probably best to reject them as well. In the end to filter out numbers outside of 1 .. 50, it may be easier to do it with text pattern matching:

case $1 in
  ([123456789] | [1234][0123456789] | 50) ;;
  (*) echo>&2 Not a decimal integer number in the 1..50 range; exit 1
esac