一 函数
① 函数的作用
1)就是把程序'多次调用相同的代码'部分定义为一份,然后给这个代码'起个名字'
2)其它所有的'重复调用'这部分代码就'只调用'这个名字即可
3)当需要'修改'这部分代码的时候,只需要'改变函数体内'的一部分代码即可实现所有调用的修改
② 函数的优势
1)把'相同的程序'定义为函数,可以'减少'整个代码的'代码量'
2)可以让程序'代码结构'更清晰
3)增加程序的'可读性',便于管理
4)可以实现'程序功能模块化',不同的程序使用函数模块化
强调:对于shell来说,linux系统的'2000多个命令'可以说是shell的函数
小结:重复调用、思路清晰、'解耦'、修改方便
③ 函数的语法
[ function ] name () compound-cmd [redirection]
1)简单语法格式
+++++++++'推荐的方式'+++++++++
function_name ()
{
statement1 # 指令
statement2
....
statementn
return n
}
2)规范语法格式
function function_name()
{
statement1 # 指令
statement2
....
statementn
return n
}
④ 函数的执行
1)无参
直接'执行函'数名 --> function_name
注意1:'执行'函数的时候,函数的'小括号()不要带'
注意2:函数'定义'以及函数体必须在'函数执行前定义',函数是'自上而下'执行的!
2)带参数的执行方法
'函数名' 参数1 参数2 ....
对比:函数的传参和'脚本传参'类似,只是'脚本'换成'函数名'即可!
3)函数后接的参数的说明
1)shell的位置参数($1、$2、$3、$4、$5、$#、$*、$?、$@)都可以是函数的参数
2)此时父脚本的参数'临时'地被函数参数所'掩盖'或隐藏
3)'$0'比较特殊,它仍然是'父脚本的名称'
4)当函数完成时,'原来'的命令行脚本的参数即'恢复'
5)在shell函数里面,'return命令'功能与shell里的exit类似,作用是'跳出函数'
6)在shell函数体里'使用exit'会退出整个'shell脚本',脚本直接'game over'
7)return语句会'返回一个退出值(返回值)'给调用函数的程序
8)函数的参数变量是在函数体里面定义,如果是'局部变量-->函数外不能调用',一般使用'local'定义
二 shell函数实践
① 无参调用函数
② 有参调用函数
在shell中,函数可以被'当作命令'一样执行,它是命令的'组合结构体'
③ local
备注: 函数中'推荐'使用'local'
④ 脚本A中调用脚本B的函数
1)自己写的一些'函数放到脚本'中,并将这些脚本放到'目录'中,然后将该目录'加入'到PATH路径
2)source 加载脚本-->'不需要前缀'
场景: 创建公共的'函数的库文件',然后可以在'不同脚本中引用'该库文件
1)脚本B
2)脚本A
3)执行
⑤ 优先级
'(function)函数' > '(alias)别名' > '命令(cmd)自身'
⑥ 继承
1)变量是会被'子进程继承'的,可以'直接'使用
2)有些情况下可能需要'继承函数',以方便'透明使用' --> 使用"export -f",'不带参数'的export只针对'变量'
1)不用export -f声明
2)使用export -f声明
⑦ return
1)shell 函数返回值只能是'整形数值' --> 否则报错"numeric argument required"
2)一般是用来表示函数'执行成功与否'的,'0'表示'成功',其他值'表示失败'
3)不带'return'关键字,也即'默认行为' --> 会返回'函数体'中'最后一个命令'的返回值
4)让函数返回一个或多个值,可以'定义全局变量',函数将计算结果'赋给全局变量',然后脚本中其他地方通过'访问全局变量',就可以获得那个函数"返回"的一个或多个执行结果了
1)默认行为
不定义'return' -->执行成功默认是'0'
shell的函数'默认'是返回0和1来表示'是否成功'的
2)return返回值只能是整数
通过return只能'返回整数值',并且是'[0-255]'的范围,超过则'截断'
3)将函数的return结果保存下来
4)其它方式保存结果
1)在'函数外'定义一个'全局'变量,然后在函数中'赋值'这个变量
2)这样'调用函数'后,全局变量就变了,达到'同样的效果'
#!/bin/sh
num=10
add(){
echo "hello"
((num++))
}
⑧ 递归
1) '结束条件'
2) '递归体'
+++++++++'计算阶乘'+++++++++
#!/bin/bash
function factorial {
if [ $1 -eq 1 ]
then
# 结束条件
echo 1
else
local temp=$[ $1 - 1 ]
# 递归调用
local result=$(factorial $temp)
echo $[ $result*$1 ]
fi
}
⑨ 递归调用问题
function ls() { ls -l; } --> '无限递归'
⑩ 小结
三 实践
① 需求1:函数传参转成脚本命令传参,对任意指定的URL判断是否异常
思路
1)'脚本传参'检查web url是否正常
2)检查的功能'写成函数'
3)函数传参转成'脚本命令传参',对任意的URL判断是否异常
1)命令行参数的测试
curl -I -m 3 -o /dev/null -s -w %{http_code} www.baidu.com
-I 仅'测试HTTP头'
-m 3 最多'查询3秒'
-o /dev/null '屏蔽'原有输出信息
-s silent 模式,'不输出任何东西'
-w %{http_code} 控制'额外'输出
2)函数的形式
#!/bin/bash
# 有系统函数库就加载进来-->用其颜色
[ -f /etc/init.d/functions ] && source /etc/init.d/functions
# 定义用法--->用户错误提示
usage(){
echo "USAGE:$0 url"
exit 1
}
# 定义函数-->明白wget相关参数的含义
Check_Url(){
wget -T 10 --spider -t 2 $1 &>/dev/null
# 定义变量-->初始化
RETVAL=$?
if [ $RETVAL -eq 0 ]
then
action "$1 url " /bin/true
else
action "$1 url " /bin/false
fi
return $RETVAL
}
# 主函数
main(){
# 判断参数的个数
if [ $# -ne 1 ];then
# 用户输入错误的提示
usage
fi
Check_Url $1
RETVAL=$?
return $RETVAL
}
# 真正开始调用函函(习惯用$*)-->传递的脚本的所有参数为整体作为函数的$1
main $*
#############测试##################
# sh function3.sh baidu.com
wget常用的命令
-T # 将所有超时设为SECONDS 秒
--spider # 不下载任何文件,测试url的有效性
-t # 置重试次数为 NUMBER (0 代表无限制),可能由于网络的原因
-d # 打入后台(daemon)
-c, --continue # 断点续传下载文件
--progress=TYPE # 选择进度条类型(dot 和 bar两种),后者是默认的
# wget通常将它的输出记录到下载目录中的wget-log 文件
-O, --output-document=FILE # 将文档写入 FILE
② 练习2:给字符串加颜色
需求:传递两个参数,第一个参数是'颜色',第二个参数是'内容',为'不同的内容'显示不同的颜色
1)规范的脚本形式
#!/bin/bash
#(1)定义颜色
RED_COLOR='\e[1;31m'
GREEN_COLOR='\e[1;32m'
YELLOW_COLOR='\e[1;33m'
BLUE_COLOR='\e[1;34m'
PINK='\e[1;35m'
# 关闭颜色
RES='\e[0m'
#(2)健壮性-->判断函数的个数
usage(){
echo "USAGE:$0 {red|green|yellow|pink}" contents
exit 1
}
#(2)使用颜色-->标准是case-->注意空格的问题,用{}解决
color(){
if [ "$1" = "red" ];then
echo -e "${RED_COLOR}$2 $RES"
elif [ "$1" = "pink" ];then
echo -e "${PINK}$2 $RES"
elif [ "$1" = "green" ];then
echo -e "${GREEN_COLOR}$2 $RES"
elif [ "$1" = "yellow" ];then
echo -e "${YELLOW_COLOR}$2 $RES"
else
usage
fi
}
main(){
if [ $# -ne 2 ];then
usage
fi
color $1 $2
}
# 函数调用
main $*
# 多行注释的方式
:<<EOF
echo -e "$RED_COLOR red $RES"
echo -e "$GREEN_COLOR GREEN $RES"
echo -e "$YELLOW_COLOR YELLOW $RES"
echo -e "$BLUE_COLOR BLUE $RES"
echo -e "$PINK PINK $RES"
EOF
2)扩展
vim /etc/DIR_COLORS
82 # 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
83 # Background color codes:
84 # 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white