shell快讲第六节--shell函数编程
shell快讲第一节--shell基础
shell快讲第二节--管道与重定向
shell快讲第三节--正则表达式
shell快讲第四节--sed与awk
shell快讲第五节--shell语法基础
shell快讲第六节--shell函数编程
shell快讲第七节--shell编程规范与调试
shell快讲第八节--shell编程实战
shell函数式编程
过程式编程
什么是过程式编程,前面我们看到的脚本都是过程式编程的脚本,它逻辑比较清晰,先执行第一行,再执行第二行,再再执行第三,好处是编写简单,按照步骤写下去就行,坏处也是很明显,如果代码超过100行,别人想读懂或者想改就费劲了,但是自己用着嗨也是可以的。
函数式编程
函数式编程从某种程度上解决了代码复用的问题,当代码量大的时候,代码复用,别人阅读你的代码都带来了便捷性,修改的时候也不用担心破坏太多的功能导致调试不方便(bash 是出了名的不方便)
1、函数语法格式,如下两种格式都是可以的,但是建议使用第一种
function name {
commands
}
-----
name () {
commands
}
2、函数的调用
函数调用,大家可以试下,如果不调用,函数是否会执行,另外函数的调用也是非常简单的,只要敲函数名字即可,对于无参的函数,直接执行。注意函数放在脚本中的位置,如果函数出现在调用命令的后面,那是会报错的
#!/bin/bash
function func1 {
echo "This is an example of a function"
}
func1 #调用无参函数
当然还有命令行调用,当然只适合简单的函数:
>>> function divem { echo $[ $1 * $2 ]; }
>>> divem 2 3
3、函数参数传递
shell的参数传递是非常暴力的方式,当然也很有效,函数的参数是我们经常会用到的,正如上面的例子是无参的函数,下面看下有参的函数
#!/bin/bash
function badfunc1 {
echo $[ $1 * $2 ] #$1 就是第一个变量 $2就是第二个变量,shell函数不会检查参数个数,这个一定要注意
}
badfunc1 2 4 #注意体会下参数传递
上面讲了字符串的传递,下面看下数组的传递,毕竟shell里面除了字符串就只有数组这两个数据类型了,当然这个数字传递我觉得有点超纲,为啥呢,因为shell根本不支持数组传递,但是我们可以通过技巧来解决这个问题,既然是技巧了,我觉得还是不掌握的好。意义不大。
#!/bin/bash
# array variable to function test
function testit {
local newarray #local定义局部变量
newarray=`echo "$@"`
echo "The new array value is: ${newarray[*]}"
}
myarray=(1 2 3 4 5)
echo "The original array is ${myarray[*]}"
testit ${myarray[*]}
4、脚本的参数传递
函数的参数传递和脚本的参数传递不是一回事,但是传递的方法是类似的,讲到了参数传递,那么就来看下脚本的参数传递,shell的参数传递还是很粗糙的
#!/bin/bash
#test.sh
function badfunc1 {
echo $[ $1 * $2 ] #这里是函数里的$1 $2
}
badfunc1 $1 $2 #这里的$1 $2 和上面的$1 $2并不一样
>>> ./test.sh 2 3 #这是调用方法
5、函数的返回值
任何一门语言的函数都有返回值,但是偏偏shell的函数的返回值处理最为奇葩,它直接返回的只有状态码,任何数据类型的返回值得用echo打印,但是我们既然学的是shell,当然就得熟悉这种传值的方法,看下面例子:
#!/bin/bash
# testing the exit status of a function
func1() {
echo "trying to display a non-existent file"
ls -l badfile
}
echo "testing the function: "
func1 #调用函数
echo "The exit status is: $?" #这里$2是返回上一行命令的状态码
我们看到了上面默认函数只能传递出状态码,状态码一般会默认,但是我们可以通过return主动抛,不过这并不实用,这里大家知道就好,因为状态码0-255,过了这个数值它就没用了,return的意愿就不大了。
#!/bin/bash
# using the return command in a function
function dbl {
read -p "Enter a value: " value
echo "doubling the value"
return $[ $value * 2 ]
}
dbl #调用函数
echo "The new value is $?"
下面我们来看点有意义的,就是字符串传递了,这样的传出的值就可以超过255了,shell是弱数据类型,数字和字符串传递方法一样,数字需要使用[]进行计算
#!/bin/bash
# using the echo to return a value
function dbl {
read -p "Enter a value: " value
echo $[ $value * 2 ]
}
result=$(dbl) #注意了,这里不是简单的函数调用,而是函数调用+接收echo传出的值,$(dbl)等价`dbl`
#result=`dbl`
echo "The new value is $result"
6、变量及变量作用域
之前我们讲了参数的传递,参数也是一种变量,但是它更多的值传递,而这里我们要将的是变量传递,变量分为全局变量和局部变量。
局部变量 顾名思义就是在局部生效的变量,它的生效范围就是函数内部,函数外部调用是无效的,局部变量就是的关键字就是local,不用local关键字就是全局变量,当然有一个更好的解决办法,就是不要让局部变量和全局变量重名。
#!/bin/bash
# demonstrating a bad use of variables
function func1 {
temp=$[ $value + 5 ]
result=$[ $temp * 2 ]
}
temp=4
value=6
func1
echo "The result is $result"
if [ $temp -gt $value ]
then
echo "temp is larger"
else
echo "temp is smaller"
fi
###################下一个脚本######################
#!/bin/bash
# demonstrating the local keyword
function func1 {
local temp=$[ $value + 5 ]
result=$[ $temp * 2 ]
}
temp=4
value=6
func1
echo "The result is $result"
if [ $temp -gt $value ]
then
echo "temp is larger"
else
echo "temp is smaller"
fi
7、脚本的退出码
前面讲到了函数的退出码,实际上函数的退出码确实不怎么重要,重要的是脚本的退出码,在多个脚本联动的时候(比如A脚本调用B脚本)那么B脚本失败了,我们就只能根据退出码判断失败了,如果我们能主动指定退出码,就能判断为啥失败,退出码使用的命令exit
#!/bin/bash
#1112rundeck.sh 无参
#date:2019.01.24
#doc:1为系统错误,2为文件不存在或者权限错误,3为未知错误
cd ../app
docker stack deploy -c app-stack.yml fhcdn
if [ $? -ne 0 ];then
echo -e "\033[31m\033[01m error:安装app失败 \033[0m"
exit 1
fi