【Linux】函数
一、函数
1、创建函数
如果定义了同名函数,则新定义的函数就会覆盖原先的定义的函数,而且在运行时不会报错。
创建函数的语法:
方法1:使用关键字function
function name {
commands
}
shell脚本中的函数名不能重复
方法2:
name() {
commands
}
函数名后的空括号name()表明正在定义的是一个函数。
2、使用函数
不能在函数定义之前调用函数,否则会报错。
#!/bin/bash
function test {
echo "测试123456"
}
count=1
while [ $count -le 5 ]
do
test
count=$[ $count + 1 ]
done
echo "循环结束!"
test
echo "脚本运行结束!"
exit
3、函数返回值
使用退出状态码
默认情况下,函数的退出状态码是函数中最后一个命令返回的退出状态码。函数执行结束后,可以使用标准变量 $? 来确定函数的退出状态码。
#!/bin/bash
func1() {
echo "尝试展示不存在的文件。"
ls -l badfile
}
echo "测试函数:"
func1
echo "退出状态码是:$?"
如下所示,退出状态码是2,因为函数中的最后一个命令执行失败了,但 echo 命令却执行成功了。 所以,使用退出状态码的方法是一种危险的方法。
使用return命令
bash shell会使用return命令以特定的退出状态码退出函数;return命令允许指定一个整数值作为函数的退出状态码。
#!/bin/bash
func2() {
read -p "请输入一个数值:" value
echo "将输入的数值翻倍。"
return $[ $value * 2 ]
}
func2
echo "新的值是 $?"
exit
当用此方法获取返回值时,需注意两点:
函数执行一结束就立刻读取返回值:如果在用$?变量提取函数返回值之前执行了其它命令,那么函数返回值就会丢失。$?变量保存的是最后执行的那个命令的退出状态码。
退出状态码必须在0~255范围内:因为退出状态码必须小于256,因此函数结果也必须是一个小于256的整数值,如果大于256就会产生错误的值。
使用函数输出
#!/bin/bash
func3() {
read -p "请输入一个数值:" value
echo "将输入的数值翻倍。"
echo $[ $value * 2 ] # 注意不是return
}
result=$(func3)
echo "新的值是$result"
exit
4、向函数传递参数
函数可以使用标准的位置变量来表示命令行中传给函数的任何参数,如函数名保存在$0变量中,函数参数依次保存在$1、$2等变量中。也可以使用特殊变量$#来确定传给函数的参数数量。
在shell脚本中调用函数时,必须将参数和函数名放在同一行。
用位置变量获取参数值
#!/bin/bash
function func4 {
if [ $# -eq 0 ] || [ $# -gt 2 ]
then
echo -1
elif [ $# -eq 1 ]
then
echo $[ $1 + $1 ]
else
echo $[ $1 + $2 ]
fi
}
echo -n "传递两个参数:"
value=$(func4 10 15)
echo $value
echo -n "只传递一个参数:"
value=$(func4 20)
echo $value
echo -n "不传递参数:"
value=$(func4)
echo $value
echo -n "传递3个参数:"
value=$(func4 10 20 36)
echo $value
要想在函数中使用脚本的命令行参数,必须在调用函数时手动将其传入。
func5() {
echo $[ $1 * $2 ]
}
if [ $# -eq 2 ]
then
value=$(func5 $1 $2)
echo "结果是$value."
else
echo "错误。"
5、函数中的变量
全局变量
全局变量在shell脚本内任何地方都有效的变量。
在默认情况下,在脚本中定义的任何变量都是全局变量。在函数外定义的变量可在函数内正常访问。
#!/bin/bash
function func1 {
value=$[ $value *2 ]
}
read -p "请输入一个值:" value
func1
echo "新的值是 $value"
局部变量
任何在函数内部使用的变量都可以被声明为局部变量,只需在变量声明之前加上关键字 local 即可:local var
也可在变量赋值语句中使用 local 关键字:local var=$[ $value + 7 ]
local关键字保证了变量仅在函数中有效,如果函数外有同名变量,那么shell会保持这两个变量的值互不干扰,意味着可以轻松地将函数变量和脚本变量分离开。
#!/bin/bash
function func2 {
local temp=$[ $value + 10 ]
result=$[ $temp * 2 ]
}
temp=5
value=8
func2
echo "结果是$result"
if [ $temp -gt $value ]
then
echo "temp更大"
else
echo "value更大"
fi
6、向函数传递数组
将数组变量当做单个参数传递的话,是不会起作用的。如果想要将数组变量作为函数参数进行传递,那么函数只会提取数组变量的第一个元素。
#!/bin/bash
function func3 {
echo "参数是:$@"
thisarray=$1
echo "接收到的数组是 ${thisarray[*]}"
}
myarray=(1 2 3 4 5 6)
echo "原始数组是:${myarray[*]}"
func3 $myarray
传递数组变量时必须先将数组变量拆解成多个数组元素,然后将这些数组元素作为函数参数传递,最后在函数内部,将所有的参数重新组合成一个新的数组变量。
#!/bin/bash
function func5 {
local newarray
newarray=(`echo "$@"`)
echo "新数组是:${newarray[*]}"
}
myarray=(1 2 3 4 5 6)
echo "原始数组是:${myarray[*]}"
func5 ${myarray[*]}
#!/bin/bash
function addarray {
local sum=0
local newarray
newarray=(`echo "$@"`)
for value in ${newarray[*]}
do
sum=$[ $sum + $value ]
done
echo $sum
}
myarray=(1 2 3 4 5 6)
echo "原始数组是:${myarray[*]}"
arg1=$(echo ${myarray[*]})
result=$(addarray $arg1)
echo "结果是 $result"
7、从函数返回数组
函数先用echo语句按正确顺序输出数组的各个元素,然后脚本再将数组元素重组成一个新的数组变量。
#!/bin/bash
function arraydb {
local origarray
local newarray
local element
local i
origarray=($(echo "$@"))
newarray=($(echo "$@"))# "$@"会将每个参数作为独立的字符串保留
element=$[ $# - 1 ] # $#表示参数数量
for (( i = 0; i <= $element; i++ ))
{
newarray[$i]=$[ ${origarray[$i]} * 2 ]
}
echo ${newarray[*]}
}
myarray=(1 2 3 4 5 6)
echo "原始数组是:${myarray[*]}"
arg1=$(echo ${myarray[*]})
result=($(arraydb $arg1))
echo "新数组是:${result[*]}"
8、函数递归
局部函数变量的一个特性是自成体系(self-containment),除了获取函数参数,自成体系函数不需要使用任何外部资源。这个特性使函数可以递归地调用,即函数通过调用自己得到结果。
递归函数通常有一个最终可以迭代到的基准值。
递归算法的经典例子就是计算阶乘。
#!/bin/bash
function factorial {
if [ $1 -eq 1 ]
then
echo 1
else
local temp=$[ $1 - 1 ]
local result=$(factorial $temp)
echo $[ $result * $1 ]
fi
}
read -p "请输入一个数值:" value
result=$(factorial $value)
echo "$value的阶乘是:$result"
exit
9、函数库
bash shell允许创建函数库文件,然后在多个shell脚本中引用此库文件。
可以通过 source 命令(也叫点号操作符)在shell脚本中运行库文件,它会在当前shell的上下文中执行命令,而不是创建新的shell并在其中执行命令。
格式:. ./绝对路径/函数库文件名
#!/bin/bash
#创建一个函数库文件
function addem {
echo $[ $1 + $2 ]
}
function multem {
echo $[ $1 * $2 ]
}
function divem {
if [ $2 -ne 0 ]
then
echo $[ $1 / $2 ]
else
echo -1
fi
}
在其它shell脚本中运行上面的函数库文件。
#!/bin/bash
#用source命令允许库文件
. ./myfuncs.sh # 该函数库文件与此脚本在同一目录下
value1=60
value2=20
result1=$(addem $value1 $value2)
echo "两数相加之和是:$result1"
result2=$(multem $value1 $value2)
echo "两数相乘之积是:$result2"
result3=$(divem $value1 $value2)
echo "两数相除之商是:$result3"
二、在命令行中使用函数
一旦在shell中定义了函数,就可以在整个系统的任意目录中使用,而不用担心该函数是否位于PATH环境变量中。
1、在命令行中创建函数
因为shell会解释用户输入的命令,所以可以在命令行中直接定义一个函数。缺点就是,在退出shell时,函数也会跟着消失
单行方式
使用单行方式定义函数时,需要在每个命令后面加分号,这样shell才能知道哪里是命令的起止。
多行方式
使用多行方式定义函数时,bash shell会使用次提示符来提示输入更多命令,此方法不需要再每条命令后面加分号,只需按下回车键即可。
当输入函数末尾的花括号 } 时,shell就能知道用户已经完成函数的定义了。