我收到了这个测试问题:
在输出中的以下几行中,写入斐波那契数列从第一项到第 n 项(含)的下一项。我们假设斐波那契数列的第一项和第二项分别为 0 和 1。
我复制了 shell 代码来生成斐波那契数列(从这里),我只需要有条件1<=n<=50
,但我不明白如何在 while 循环之后添加它:
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"
答案1
您可以在循环之前执行此操作以中止该函数:
if [[ $n -lt 1 ]] || [[ $n -gt 50 ]]
then
return
fi
您还可以像这样限制输入值:
if [[ $n -lt 1 ]]
then
n=1
fi
if [[ $n -gt 50 ]]
then
n=50
fi
这是带有第一个选项的代码的工作版本:
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"
答案2
请注意,在 bash 和其他类似 Korn 的 shell 中,在算术表达式中使用未经清理的数据其中包括 Korn 风格的((...))
和构造$((...))
内部算术运算符的参数,[[...]]
这引入了任意命令执行漏洞。
expr
通常无法可靠使用,并且已经过时了几十年。
因此,在任何算术上下文中使用输入之前,您应该对输入进行清理,以确保它是您期望的格式的有效数字。
在 bash 算术表达式中,带有前导零的数字被解释为八进制,因此最好也拒绝它们。最后要过滤掉 1 .. 50 之外的数字,使用文本模式匹配可能会更容易:
case $1 in
([123456789] | [1234][0123456789] | 50) ;;
(*) echo>&2 Not a decimal integer number in the 1..50 range; exit 1
esac
答案3
在现代 shell 中,避免旧的已弃用的数学语法和反引号,增强可读性:
#!/bin/bash
fib(){
x=0 y=1 i=2 n=$1
((n < 1 || n > 50)) && return
echo "Fibonacci Series up to $n terms :"
echo "$x"
echo "$y"
while ((i++ < n)); do
z=$((x+y))
echo "$z"
x=$y y=$z
done
}
read -p 'Type an integer between 1 and 50 as max terms >>> ' n
r=$(fib $n)
echo "$r"
((...))
和$((...))
是算术命令,如果表达式非零,则返回退出状态 0;如果表达式为零,则返回 1。如果需要副作用(分配),也用作“let”的同义词。看http://mywiki.wooledge.org/ArithmeticExpression。
反引号用于旧式命令替换。foo=$(command)
建议改用该语法。内部的反斜杠处理$()
并不令人惊讶,并且$()
更容易嵌套。看http://mywiki.wooledge.org/BashFAQ/082
expr
是古代 shell 代码中用来做数学的程序。在 bash 等 Posix shell 中,使用$(( expression ))
.在 bash、ksh、mksh、pdksh、yash、dash、ash、sh 或 zsh 中,您还可以使用(( expression ))