13 函数.docx
《13 函数.docx》由会员分享,可在线阅读,更多相关《13 函数.docx(18页珍藏版)》请在冰点文库上搜索。
![13 函数.docx](https://file1.bingdoc.com/fileroot1/2023-4/29/b49dea7d-212e-4a81-8f3d-9581936db1fc/b49dea7d-212e-4a81-8f3d-9581936db1fc1.gif)
13函数
13函数
在LinuxShell中,所有函数定义都是平行的,即不允许在函数体内再定义其他的函数,但允许函数之间相互调用。
13.1、函数的定义和基础知识
在LinuxShell中函数的返回值只能为退出状态0或1,其基本形式为:
function_name()
{
command1
command2
...
commandN
}
在函数名前可以加上关键字function,但加上和省略关键字function对脚本的最终执行不产生任何影响。
函数体中的命令集合必须含有至少一条命令,即函数不允许空命令。
函数之间可通过参数、参数返回值通信,函数在脚本中出现的次序可以是任意的,但是必须按照脚本中的调用次序执行这些函数。
例:
一个简单的函数调用过程
#!
/bin/bash
hello()
{
echo"Helloeveryone!
"
}
echo"Nowgoingtorunfunctionhello()"#调用hello函数
hello
echo"endthefunctionhello()"#提示结束函数调用
结果:
Nowgoingtorunfunctionhello()
Helloeveryone!
endthefunctionhello()
在Shell中不需要声明就可直接定义函数,但是在调用函数前需对它进行定义。
由于所有的脚本程序都是从顶部开始执行的,所以,需要首先定义函数,然后才能对函数进行调用,以此来保证函数能被正常使用。
例:
实现在循环中调用函数
#!
/bin/bash
output()
{
for((num1=1;num1<=5;num1++))
do
echo-n"$num1"
done
}
let"num2=1"
while["$num2"-le3]
do
output
echo""
let"num2=num2+1"
done
结果:
12345
12345
12345
例:
用函数来显示当前目录中存在多少个文件和多少个子目录
#!
/bin/bash
directory()
{
let"filenum=0"
let"dirnum=0"
ls$1#显示当前目录下所有的子目录和文件,并使用echo换行
echo""
forfilein$(ls)
do
if[-d$file]
then
let"dirnum=dirnum+1"#判断为子目录
else
let"filenum=filenum+1"#判断为文件
fi
done
echo"Thenumberofdirectoriesis$dirnum"
echo"Thenumberoffilesis$filenum"
}
directory
13.2、向函数传递参数
在bashShell编程中,向函数传递的参数仍然是以位置参数的方式来传递,而不能传递数组等其他形式变量。
例:
用于说明函数如何传递参数和传值前后的变量值如何变化
#!
/bin/bash
half()
{
let"n=$1"#将参数传递给n
let"n=n/2"
echo"Infunctionhalf()nis$n"
}
let"m=$1"
echo"Beforethefunctionhalf()iscalled,mis$m"#显示函数调用前m值
half$m#显示函数调用时n值
echo"Afterthefunctionhalf()iscalled,mis$m"#显示函数调用后m值
执行:
./function4.sh10
结果:
Beforethefunctionhalf()iscalled,mis10
Infunctionhalf()nis5
Afterthefunctionhalf()iscalled,mis10
由脚本可知,函数的参数复制的是调用时对应的参数值,而函数通过一些命令可以对参数进行运算或处理,仅改变函数内参数的值,但不会影响原参数的值。
例:
用于实现两数的四则运算
#!
/bin/bash
count()
{
if[$#-ne3]#判断参数个数是否不等于3,不等于3表示输入参数错误
then
echo"Thenumberofargumentsisnot3!
"
fi
let"s=0"
case$2in
+)
let"s=$1+$3"
echo"$1+$3=$s";;
-)
let"s=$1-$3"
echo"$1-$3=$s";;
\*)
let"s=$1*$3"
echo"$1*$3=$s";;
\/)
let"s=$1/$3"
echo"$1/$3=$s";;
*)
echo"Whatyouinputiswrong!
";;
esac
}
echo"Pleasetypeyourword:
(e.g.1+1)"
readabc#读取输入的参数
count$a$b$c
在LinuxShell编程中,函数还可以传递间接参数。
例:
演示函数如何传递间接参数
#!
/bin/bash
ind_func()#用于显示参数值
{
echo"$1"
}
#设置间接参数
parameter=ind_arg
ind_arg=Hello
ind_func"$parameter"#显示直接的参数
ind_func"${!
parameter}"#显示间接参数
echo"*************************"#改变ind_arg值后的情况
ind_arg=World
ind_func"$parameter"
ind_func"${!
parameter}"
结果:
#ind_arg的值改变前parameter变量的直接参数值和间接参数值
ind_arg
Hello
*************************
#ind_arg的值改变前parameter变量的直接参数值和间接参数值
ind_arg
World
13.3、函数返回值
在LinuxShell编程中,函数通过return返回其退出状态,0表示无错误,1表示有错误。
在脚本中可以有选择地使用return语句,因为函数在执行完最后一条语句后将执行调用该函数的地方执行后续操作。
返回值return最大返回255。
例:
根据用户输入显示星期
#!
/bin/bash
show_week()
{
echo-n"Whatyouinputis:
"
echo"$1"
case$1in
0)
echo"TodayisSunday."
return0;;
1)
echo"TodayisMonday."
return0;;
2)
echo"TodayisTuesday."
return0;;
3)
echo"TodayisWednesday."
return0;;
4)
echo"TodayisThursday."
return0;;
5)
echo"TodayisFriday."
return0;;
6)
echo"TodayisSaturday."
return0;;
*)
return1;;
esac
}
ifshow_week"$1"#在if中调用函数
then
echo"Whatyouinputisright!
"
else
echo"Whatyouinputiswrong!
"
fi
exit0
执行:
./function7.sh2#当return为0时的输出结果
结果:
Whatyouinputis:
2
TodayisTuesday.
Whatyouinputisright!
执行:
./function7.sh33#当return为1时的输出结果
结果:
Whatyouinputis:
33
Whatyouinputiswrong!
13.4、函数调用
13.4.1、脚本放置多个函数
可以在脚本放置多个函数,脚本执行时按照调用函数的顺序执行这些函数。
例:
实现在脚本中放置多个函数
#!
/bin/bash
show_week()
{
fordayinMondayTuesdayWednesdayThursdayFridaySaturdaySunday
do
echo-n"$day"
done
}
show_number()
{
for((integer=1;integer<=7;integer++))
do
echo-n"$integer"
done
}
show_square()
{
i=0;
until[["$i"-gt2]]
do
let"square=i*i"
echo"$i*$i=$square"
let"i++"
done
}
show_week
echo“”
show_number
echo“”
show_square
结果:
MondayTuesdayWednesdayThursdayFridaySaturdaySunday
1234567
0*0=0
1*1=1
2*2=4
13.4.2、函数相互调用
在LinuxShell编程中,函数之间可以相互调用,调用时会停止当前运行的函数转去运行被调用的函数,直到调用的函数运行完,再返回当前函数继续运行。
例:
实现函数相互调用
#!
/bin/bash
square()
{
echo"Pleaseinputthenum:
"
readnum1
let"squ=num1*num1"
echo"Squareof$num1is$squ."
}
cube()
{
echo"Pleaseinputthenum:
"
readnum2
let"c=num2*num2*num2"
echo"Squareof$num2is$c."
}
power()
{
echo"Pleaseinputthenum:
"
readnum3
echo"Pleaseinputthepower:
"
readp
let"temp=1"
for((i=1;i<=$p;i++))
do
let"temp=temp*num3"
done
echo"power$pof$num3is$temp."
}
choice()
{
echo"Pleaseinputthechoiceofoperate(sforsquare;cforcubeandpforpower):
"
readchar
case$charin
s)
square;;
c)
cube;;
p)
power;;
*)
echo"Whatyouinputiswrong!
";;
esac
}
choice
13.4.3、一个函数调用多个函数
在LinuxShell编程中,允许一个函数调用多个函数,在该函数调用其他函数时同样需要按照调用的顺序来执行调用的函数。
例:
显示一个不多于5位的正整数的位数,并按顺序显示各个数位的值
#!
/bin/bash
count_of_int()
{
if[$1-gt9999]
then
let"place=5"
elif[$1-gt999]
then
let"place=4"
elif[$1-gt99]
then
let"place=3"
elif[$1-gt9]
then
let"place=2"
else
let"place=1"
fi
echo"Theplaceofthe$1is$place."
}
num_of_int()
{
let"ten_thousand=$1/10000"
let"thousand=$1/1000%10"
let"hundred=$1/100%10"
let"ten=$1/10%10"
let"indiv=$1%10"
if[$ten_thousand-ne0]
then
echo"$ten_thousand$thousand$hundred$ten$indiv"
elif[$thousand-ne0]
then
echo"$thousand$hundred$ten$indiv"
elif[$hundred-ne0]
then
echo"$hundred$ten$indiv"
elif[$ten-ne0]
then
echo"$ten$indiv"
else
echo"$indiv"
fi
}
show()
{
echo"Pleaseinputthenumber(1-99999):
"
readnum
count_of_int$num
num_of_int$num
}
show
结果:
Pleaseinputthenumber(1-99999):
56485
Theplaceofthe56485is5.
56485
13.5、局部变量和全局变量
在LinuxShell编程中,可以通过local关键字在Shell函数中声明局部变量,局部变量将局限在函数范围内。
此外,函数也可调用函数外的全局变量,如果一个局部变量和一个全局变量的名字相同,则在函数中局部变量将会覆盖掉全局变量。
例:
调用局部变量和全局变量
#!
/bin/bash
text="globalvariable"
use_local_var_fun()
{
localtext="localvariable"
echo"Infunctionuse_local_var_fun"
echo$text
}
echo"Executethefunctionuse_local_var_fun"
use_local_var_fun
echo"Outoffunctionuse_local_var_fun"
echo$text
exit0
结果:
Executethefunctionuse_local_var_fun
Infunctionuse_local_var_fun
localvariable
Outoffunctionuse_local_var_fun
globalvariable
13.6、函数递归
LinuxShell中可以递归调用函数,即函数可以直接或间接地调用其自身。
例:
函数递归调用
#!
/bin/bash
foo()
{
ready
foo$y
echo"$y"
}
foo
exit0
这个递归函数是不正确的。
为了防止递归函数调用无终止地进行,必须在函数内有终止递归的条件,常用的办法是加条件判断,满足某种条件后就不再进行递归调用,然后逐层返回。
13.6.1、使用局部变量的递归
使用局部变量进行递归一般是针对数值运算来使用的。
阶乘运算n!
可用该公式来实现:
n!
=1(n=0)
n!
=n*(n-1)!
(n>=1)
例:
使用局部变量的函数递归调用
#!
/bin/bash
fact()
{
localnum=$1
if["$num"-eq0]
then
factorial=1
else
let"decnum=num-1"
fact$decnum
let"factorial=$num*$?
"
fi
return$factorial
}
fact$1
echo"Factorialof$1is$?
"
exit0
执行:
./function13.sh5
结果:
Factorialof5is120
13.6.2、不使用局部变量的递归
例:
通过不使用局部变量的函数递归实现汉诺塔
#!
/bin/bash
move=0
dohanoi()
{
if[$1-eq0]#输入圆盘的个数为0
then
echo-n""
else
dohanoi"$(($1-1))"$2$4$3#把A上的n-1个圆盘移到B上
echo"move$2---->$3"
let"move=move+1"#把A上的一个圆盘移到C上
dohanoi"$(($1-1))"$4$3$2#把B上的n-1个圆盘移到C上
fi
if[$#-eq1]#递归函数出口
then
if[$(($1>1))-eq1]#至少要有一个圆盘
then
dohanoi$1ACB
echo"Totalmoves=$move"
else
echo"Thenumberofdiskwhichyouinputisillegal!
"
fi
fi
}
echo"Pleaseinputthenumofdise:
"
readnum
dohanoi$num'A''B''C'
结果:
Pleaseinputthenumofdise:
3
moveA---->B
moveA---->C
moveB---->C
moveA---->B
moveC---->A
moveC---->B
moveA---->B
该脚本把圆盘都移动到B上。