1. shell中的函数
1.1 函数优点
函数的优点:代码模块化,调用方便,节省内存;代码量少,排错简单; 可以改变代码的执行顺序
1.2 函数语法
语法一(推荐使用):
函数名 () {
代码块
return N
}
语法二:
function 函数名 {
代码块
return N
}
1.3 函数应用
shell中调用函数时,不用加小括号,直接写函数名就可以。
实现一个10的阶乘函数。
注意: 使用 let方式进行计算时,调用变量时可以不用写 $符;双小括号(()) 必须得写 $符。
例子中 循环体的五种计算方式都可以, 推荐使用 let 方式来计算。
#!/bin/bash
factorial() {
result=1
for((i=1; i<=10; i++))
do
#result=$(($result * $i))
#let result=$result*$i
#let result=result*i
#let result*=$i
let result*=i
done
echo "10的阶乘为$result"
return 0
}
# 调用函数,不用加()
factorial
1.4 函数传参
1. 位置传参
#!/bin/bash
factorial() {
result=1
for((i=1; i<=$1; i++))
do
result=$(($result * $i))
done
echo "$1的阶乘为$result"
return 0
}
# 调用函数,不用加()
factorial $1
factorial $2
factorial $3
# 结果如下
3的阶乘为6
5的阶乘为120
10的阶乘为3628800
2. 数组传参
第一种:把数组的所有元素分散开传进函数,然后在函数内部用 $@ 或 $* 或 "$@"来接收所有参数,但是不能用 "$*"接收;是有区别的(具体区别见https://www.cnblogs.com/bk9527/p/12663949.html,预变量有详细说明)。
#!/bin/bash
arr=(1 2 3 4 5)
get_sum() {
sum=0
for i in $*;do
let sum+=i
done
echo $sum
}
echo "get the array sum is `get_sum ${arr[@]}`"
结果如下:
get the array sum is 15
第二种:给函数传参时 用 函数名 "${数组名[@]}"。当 "$*" 用双引号引起来时,会将所有的参数从整体上看做一份数据,而不是把每个参数都看做一份数据。
#!/bin/bash
arr_origin=(5 8 9)
get_sum() {
arr=($1) # 用()括起来, 和入参的长度保持一致
echo "个数: ${#arr[@]}"
result=0
for i in ${arr[@]}; do
let result+=i
done
echo $result
}
get_sum "${arr_origin[*]}" # 一定要使用 "$*", 并用双引号引起来,即将数组的所有元素看做一份数据,传入函数中的arr就是数组所有的元素。
# 如果用 "$@", 那么传入函数中的arr变量就只有数组的第一个元素——5,就犯错了!!!
3. 数组入参, 数组出参
传入一个数组,并把处理后的数组传出。
注意:在shell中,不管是在函数外部还是函数里面,如果不加local声明的话,那么这些个变量都是全局变量,即使在函数内部声明的变量,在函数外部也能调用。
为了防止冲突,在函数内部使用的变量,最好用local声明,表示局部变量,仅函数内部使用。
#!/bin/bash
#传入一个数组,将处理后的数组传出
arr=(1 2 3)
out_arr_func() {
local n # 这里的local表示 变量n 和变量out_arr 都是局部变量, 在函数外部不能引用。
local out_arr
for i in $*; do
out_arr[n++]=$(($i * 5))
done
echo ${out_arr[*]}
}
#result=`out_arr_func ${arr[*]}`
#echo "the result is $result"
#echo "in the function out_arr is ${out_arr[*]}"
#result=$(out_arr_func ${arr[*]})
#echo "the result is $result"
#echo "in the function out_arr is ${out_arr[*]}"
out_arr_func ${arr[*]}
echo "in the function out_arr is ${out_arr[*]}"
1.5 shell函数返回值
1. return 返回值 -- 即函数的执行状态
在 C++、Java、C#、Python 等大部分编程语言中,返回值是指函数被调用之后,执行函数体中的代码所得到的结果,这个结果就通过 return 关键字返回;
但是 Shell 中的 return 返回值表示的是函数的退出状态:默认的返回值为 0 表示函数执行成功了,返回值为非 0 表示函数执行失败(出错)了。if、while、for 等语句都是根据函数的退出状态来判断条件是否成立。函数执行失败时,我们可以自定义return返回值,这样就可以根据返回值(退出状态)来判断具体出现了什么错误,比如一个打开文件的函数,我们可以指定 1 表示文件不存在,2 表示文件没有读取权限,3 表示文件类型不对。
$? 是一个特殊变量,用来获取上一个命令的退出状态,或者上一个函数的返回值,我们可以根据 $? 来获取上一个函数的执行状态(执行成功或执行失败的类型)
#!/bin/bash test() { echo "arg1 = $1" if [ $1 == "1" ]; then return 111 else return 100 fi } test 1 echo "该函数的执行状态值为$?"
执行结果如下:
arg1 = 1
该函数的执行状态值为111
2. echo 返回值 -- 获取函数处理后的结果
如何得到函数的处理结果呢?比如,定义了一个函数,计算从 m 加到 n 的和,最终得到的结果该如何返回呢?
这个问题有两种解决方案:
一种是借助全局变量,将得到的结果赋值给全局变量,直接使用全局变量
#!/bin/bash result=1 # 全局变量 factorial() { result=1 for((i=1; i<=10; i++)) do let result*=i done return 198 } factorial echo "the last result is $result"
结果如下:
the last result is 3628800
一种是在函数内部使用 echo、printf 命令将结果输出,在函数外部使用$()或者``捕获结果。
#!/bin/bash
factorial() {
result=1
for((i=1; i<=10; i++))
do
let result*=i
done
echo "10的阶乘为$result"
return 198
}
out_result=`factorial`
echo "the last result is $out_result"
echo "the last result also is $(factorial)"
结果如下:
the last result is 10的阶乘为3628800
the last result also is 10的阶乘为3628800
`` 或 $() 捕获了echo的输出结果,并将结果赋值给变量out_result 或 直接输出结果。