Shell函数
1 Shell函数
Shell 函数用于存放一系列的指令。
在 Shell 脚本执行的过程中,函数被置于内存中,每次调用函数时不需要从硬盘读取,因此运行的速度比较快。
在 Shell 编程中函数并非是必须的元素,但使用函数可以对程序进行更好的组织。
将一些相对独立的代码变成函数,可以提高程序可读性与重用性,避免编写大量重复代码。
1.1 函数定义
- 函数定义
function 函数名(){
命令序列
return 返回值
}
function:表示定义一个函数,可以省略
{:表示函数执行命令的入口,该符号可以与函数名同行也可以在函数名下一行的句首;}:表示函数体结束;两个大括号之间{ }是函数体
命令序列:可以是任意的 Shell 命令,也可以调用其他函数。
return:退出函数返回一个退出值,通过返回值判断执行是否成功,也可以使可以用 exit 终止整个Shell 脚本。
return和exit的区别在于它们的作用范围:return只作用于函数内部,而exit作用于整个脚本。
如果想从函数中返回一个值并继续执行脚本,应该使用return语句
如果想在任何时候结束整个脚本的执行,应该使用exit语句
函数返回值可以用 $?变量显示
范围在0~255之间,如果超过了就使用256进行取余
如果没加返回值,则将最后一条命令的运行结果作为返回值
- 函数调用
函数名 [参数1] [参数2] …
- 示例
#!/bin/bash
# return与exit的区别
function hello1(){echo "hello one"# 退出函数return 111
}
function hello2(){echo "hello two"# 退出脚本exit 222
}
echo "hello1开始"
hello1
echo $?
echo "hello1结束"
echo "hello2开始"
hello2
echo $?
echo "hello2结束"
#!/bin/bash
# 遇到错误的命令不会停止,会继续执行后面的命令
function error(){lsrecho "error"
}
error
echo $?
#!/bin/bash
# 函数可以嵌套调用
# 如果存在重名函数,会优先调用在它上方离它最近的函数,这是加载顺序导致的
function fun1(){echo "fun1"
}
function fun2(){fun1echo "fun2"fun3
}
# 函数fun3尚未被加载,无法被调用
# 通常函数写在最上面,调用在所有函数的最后
#fun2
function fun3(){fun1echo "fun3"
}
fun2
1.2 函数的参数
- 语法
函数名称 参数1 参数2 参数3 …
在使用函数参数时,函数名称在前参数在后,函数名和参数之间用空格分隔,可以有多个参数,参数使用$1、$2、$3......
的方式表示。
从第 10 个参数开始,调用方法为${10},不加大括号无法调用成功。
- 示例
#!/bin/bash
# 使用自定义变量获取参数
function fun1(){read -p "输入第一个数字:" num1read -p "输入第二个数字:" num2echo "$num1+$num2=$(echo $num1+$num2|bc)"# 返回值不能超过255,超过的用255取余return $(echo $num1+$num2|bc)
}
fun1
echo $?
#!/bin/bash
# 使用预定义变量获取参数
function fun2(){echo $1echo $2echo $3# 不加大括号,$12表示$1和数字2echo $12echo ${12}
}
# fun2 aa bb cc dd ee ff gg hh ii jj kk ll
1.3 处理参数的特殊字符
参数 | 说明 |
---|---|
$# | 传递的脚本或函数的参数的个数 |
$* | 以字符串显示所有向脚本传递的参数 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但使用时加引号 |
$- | 显示shell使用的当前选项,与set命令功能相同 |
$? | 显示最后命令的退出状态,0表示没有错误,其它表示有错误 |
function fun3(){echo "第一个参数为:$1"echo "第二个参数为:$2"echo "第十个参数为:${10}"echo "参数总数为:$#"echo "所有参数为:$*"echo "脚本当前的ID号:$$"
}
fun3 0 1 2 3 4 5 6 7 8 9 a b
echo $?
1.4 跨文件调用函数
# funa.sh文件
#!/bin/bash
function funa(){echo "This is funa"
}
# funb.sh文件
#!/bin/bash
function funb(){echo "This is funb"
}
funb
# 跨文件调用
source /test/fun/funa.sh
funa
1.5 函数变量的作用范围
函数在Shell脚本中仅在当前Shell环境中有效
Shell脚本中的变量默认全局有效
将变量限定在函数内部使用local命令
#!/bin/bash
# 变量作用域范围
num1=111
function fun(){# 默认为全局变量num2=222echo $num2# 定义为局部变量,只在函数内有效;全局变量和局部变量不是同一个变量local num1=100echo $num1
}
num2=000
fun
echo $num1 $num2
1.6 函数递归
函数调用自身
#!/bin/bash
# 递归求阶乘
function fact(){if [ $1 -eq 1 ]thenecho 1else# echo $1*$(fact $(echo $1-1|bc))|bc# 将步骤拆分成三步local next=$(($1-1)) # 计算n-1的值local result=$(fact $next) # 计算(n-1)!echo $(($1*$result)) # 计算最终结果fi
}
fact 5
# 递归目录
#!/bin/bash
function list_files(){files=$(ls $1)for i in $filesdoif [ -d "$1/$i" ]thenecho "$i 是目录"list_files "$1/$i"elseecho "$i 是文件"fidone
}
list_files /test/fun
1.7 函数库
只包含函数的定义的特殊脚本文件,可以供其他脚本进行使用
# fun6.sh作为函数库
#!/bin/bash
function jiafa(){echo $[$1+$2]
}
function jianfa(){echo $[$1-$2]
}
function chengfa(){echo $[$1*$2]
}
function chufa(){echo $[$1/$2]
}
# fun7.sh调用函数库
#!/bin/bash
source fun6.sh
read -p "输入第一个参数:" num1
read -p "输入第二个参数:" num2
echo "$num1+$num2=$(jiafa $num1 $num2)"
echo "$num1-$num2=$(jianfa $num1 $num2)"
echo "$num1*$num2=$(chengfa $num1 $num2)"
echo "$num1/$num2=$(chufa $num1 $num2)"
1.8 函数实战
#!/bin/bash# 定义输出目录
output_dir="/test/fun/system_report"
mkdir -p "$output_dir"# 获取CPU使用情况
get_cpu_use(){echo "CPU使用情况"# -b:批处理模式运行 -n1:只运行一次就退出top -bn1 | grep "Cpu{s}"echo ""
}# 获取内存使用情况
get_memory_use(){echo "内存使用情况"free -hecho ""
}# 磁盘使用情况
get_disk_use(){echo "磁盘使用情况"df -hecho ""
}# 生成系统报告
get_report(){local report_file="$output_dir/report_$(date +%Y-%m-%d_%H:%M:%S).txt"echo "系统性能报告-$(date)" > "$report_file"echo "" >> "$report_file"get_cpu_use >> "$report_file"get_memory_use >> "$report_file"get_disk_use >> "$report_file"
}# 循环调用
while [ $i -eq 1 ]
doget_report# 没小时生成一次报告sleep 3600
done