shell函数
函数的作用
-------------函数的定义(两种方式)---------------
1
function 函数名 {
command
} //这是一种规范写法
2
函数名(){ //最常用因为最简洁
command
}
函数定义完之后并不会自动执行,需要调用才行,好处在于可以写一段功能代码作为函数,有需要就直接调用
定义的时候哪怕出现语法错误也没关系,不调用就不会报错
当然我们写函数最终目的还是为了调用,为了实现某个功能块
函数返回值:
return表示退出函数并返回一个退出值,脚本中可以用
?
变
量
显
示
该
值
使
用
原
则
:
1
、
函
数
一
结
束
就
取
返
回
值
,
因
为
?变量显示该值 使用原则: 1、函数一结束就取返回值,因为
?变量显示该值使用原则:1、函数一结束就取返回值,因为?变量只返回执行的最后一条命令的退出状态码
2、退出状态码必须是0~255,超出时值将为取余256
例
444 % 256
函数的调用
直接在脚本里定义函数的代码块后写函数名即可完成调用
#!/bin/bash
function fun1 { //定义了一个函数叫做fun1
echo "this is a function!" //函数体的功能是打印"this is a function!
}
fun1 //直接写函数名就会运行函数体内的代码
[root@server myscripts]# . fun.sh
this is a function!
注意①:函数名必须是唯一,如果先定义了一个,再用同样的名称定义,第二个会覆盖第一个的功能,出现了你不想要的结果,所以这里一定要注意不要重名!
#!/bin/bash
f1 (){
echo hello
}
f1 (){
echo world
}
f1
[root@localhost ~]# . f1.sh
world
注意②:调用函数之前必须先进行定义!
#!/bin/bash
f1 (){
echo hello
}
f3 (){
echo “$(f1) $(f2)”
}
f2 (){
echo world
}
f3
[root@localhost ~]# bash f1.sh //因为f3函数里调用了f2,调用了f3的时候并不能知道f2的定义,因为f2在f 运行之后才被定义,所以运行的脚本会报错
f1.sh:行8: f2: 未找到命令
hello
#!/bin/bash
f1 (){
echo hello
}
f3 (){
echo “$(f1) $(f2)” //这里虽然提前调用了f2,但是f2的函数还是在运行f3之前定义的所以他能够找到
}
f2 (){
echo world
}
f3
注意③:不一定要在脚本开头就定义函数,只要调用之前定义就可以
如果是在其他地方嵌套调用等情况,不可以直接写函数的值,避免无法识别,可以用反撇号引起来,相当于是调用函数的结果
#!/bin/bash
f1 (){
echo hello
}
f2 (){
echo world
}
f3 (){
echo “f1
f2
” //这里如果直接是f1和f2的话,打印出来的不会是hello world而会是f1 f2
}
f3
cat </etc/yum.repos.d/local.repo
[local]
name=local
baseurl=file:///mnt
enabled=1
gpgcheck=0
EOF
vim localrepo. sh
#!/bin/bash
function backuprepo {
cd /etc/yum.repo.d
mkdir repo.bak
mv * .repo repo.bak
mount /dev/sr0 /mnt > /dev/null
}
makelocalrepo() {
echo ‘[local]
name= local
baseurl=file: / , /mnt
enabled=1
gpgcheck=0’ > local.repo
}
uselocal repo (){
yum clean all > /dev/null
yum makecache > /dev/null
yum install -y httpd > /dev/null
}
######main#######
backuprepo
makelocalrepo
uselocalrepo
--------return---------
#!/bin/bash
function test1 {
read -p “请输入一个数字” num
return
[
[
[num*2]
}
test1
echo $?
test2 () {
read -P “请输入值2:” NUM
echo
[
[
[NUM*2]
}
res=$(test2)
echo
[
[
[res *2]
函数传参
1.两个数求和
#!/bin/bash
sum(){
read -p “请输入第一个数:” NUM1
read -p “请输入第二个数:” NUM2
echo "你输入的两个数为:
N
U
M
1
和
NUM1 和
NUM1和NUM2 "
SUM=
(
(
N
U
M
1
+
(( NUM1+
((NUM1+NUM2))
echo “两个数的和为: $SUM”
}
sum
函数的作用范围
在 Shell 脚本中函数的执行并不会开启一个新的子 Shell,而是仅在当前定义的 Shell 环境中有效。如果Shell脚本中的变量没有经过特殊设定,默认在整个脚本中都是有效的。在编写脚本时,有时需要将变量的值限定在函数内部,可以通过内置命令local来实现。函数内部变量的使用,可以避免函数内外同时出现同名变量对脚本结果的影响。
shell脚本中变量默认全局有效
local命令:将变量限定在函数内部使用
[root@localhost ~]# vim myfun.sh
myfun ()
{
local i
i=8
echo $i
}
i=9
myfun
echo $i
上述脚本中myfun 函数内部使用了local命令设置变量i,其作用是将变量i限定在函数内部。myfun 函数外部同样定义了变量i,内部变量i和全局变量i互不影响。脚本执行时先调用了函数myfun,函数内部变量i为8,所以输出结果是8。调用完函数之后,给变量i赋值为9,再打印外部变量i,所以又输出 9
myfunc() {
a=8
echo $a
}
myfunc
echo $a
#!/bin/bash
myfunc() {
a=8
echo $a
myfunc
a=9
echo $a I
函数的参数
函数的传参
函数的参数
计算位置变量$1和$2的和
#!/bin/bash
add (){
let sum=$1+$2 //这里的位置变量是函数的位置变量,所以要写在调用函数的后面,如果是调用脚本时使用则 不能成功
echo $sum
}
add 4 5
脚本的参数
#!/bin/bash
add (){
let sum=$1+$2
echo $sum
}
add $1 $2 //这里相当于调用了脚本的参数了,然后把脚本的位置变量传递给函数进行计算
通过脚本传递参数给函数中的位置参数$1
#!/bin/bash
fun1(){
rm -rf $1
}
fun1 $1
调用函数时直接传递参数
#!/bin/bash fun1(){
rm -rf $1
}
fun1 /root/a.txt
函数中多参数传递和使用方法
案例:阶乘
#!/bin/bash
jiecheng (){
cheng=1
for i in {1…6}
do
let cheng=
i
∗
i*
i∗cheng
done
echo $cheng
}
jiecheng
优化版:根据用户需求算几的阶乘
#!/bin/bash
jiecheng (){
cheng=1
read -p “请问您想算几的阶乘:” num //①给用户提示输入
for i in seq $num
do
let cheng=
i
∗
i*
i∗cheng
done
echo $cheng
}
jiecheng
#!/bin/bash
jiecheng (){
cheng=1
for i in seq $1
//②用位置变量的方式
do
let cheng=
i
∗
i*
i∗cheng
done
echo $cheng
}
jiecheng $1
函数的返回值,用return来自定义返回码
函数的返回值就是函数当中运行最后一条命令的状态码,默认成功为0,失败为非0值,可以通过$?查看
但是可以自己自定义返回码,用return
1、return的值范围是0-255
2、遇到return即结束函数不会再往下执行
#!/bin/bash
HELLO (){
echo “hello world”
}
HELLO //执行成功 echo $?为0
#!/bin/bash
HELLO (){
echo “hello world”
ls xxxx
}
HELLO //执行失败 echo $?为非0,因为没有xxxx的文件
#!/bin/bash
HELLO (){
echo “hello world”
return 11
}
HELLO //执行成功 echo $?为11
#!/bin/bash
HELLO (){
echo “hello world”
return 11 //返回码为11,不会执行下面的命令了
ls xxxxx
return 22
}
HELLO
例1:测试文件是否存在
#!/bin/bash
file=/etc/xxxx
f1 (){
if [ -f $file ];then
return 100
else
return 200
fi
}
f1
echo $? //返回码为200,我们可以根据返回值来判断我们想要的结果
例2:两个数之和
#!/bin/bash
SUM (){
let sum=$1+$2
echo $sum
return 100
}
SUM 5 5
echo $?
[root@localhost ~]# . re2.sh
10
100
#!/bin/bash
SUM (){
let sum=$1+$2
echo $sum
return 100
}
SUM 5 5
num=SUM 5 5
//注意这里函数是有参数的
echo $?
echo
n
u
m
这
个
脚
本
返
回
码
为
10
/
/
先
执
行
了
函
数
,
函
数
的
结
果
是
10100
/
/
执
行
函
数
之
后
返
回
码
是
10010
/
/
把
函
数
的
结
果
10
赋
值
给
了
num 这个脚本返回码为 10 //先执行了函数,函数的结果是10 100 //执行函数之后返回码是100 10 //把函数的结果10赋值给了
num这个脚本返回码为10//先执行了函数,函数的结果是10100//执行函数之后返回码是10010//把函数的结果10赋值给了num,所以是10
本地变量与全局变量
在脚本里定义的变量或者在函数体没有声明为本地变量的都为全局变量,意思是在当前shell环境都识别
如果需要这个变量只在函数中使用则可以在函数中用local关键字声明,这样即使函数体外有个重名的变量也没关系,不影响在函数体的使用
如果是用source执行脚本的话就能看出差别
[root@localhost ~]# a=nihao
#!/bin/bash //写一个函数,首先打印a的值,然后改变a的值再打印
f1 (){
echo $a
a=world
echo $a
}
f1
[root@localhost ~]# source f1.sh //用source执行脚本,会发现a的值改变了
nihao
world
[root@localhost ~]# echo $a
world
在函数体中用local定义变量a的值
#!/bin/bash
f1 (){
echo $a
local a=world
echo $a
}
f1
[root@localhost ~]# source f1.sh //执行脚本发现a的值并没有改变
world
world
#!/bin/bash
f1 (){
echo $a
local a=world
echo $a
}
f1
echo $a
[root@localhost ~]# a=hello
[root@localhost ~]# source f1.sh //可以看成变量a的值在函数体设为了本地变量所以只在函数体中生效
hello
world
hello
#!/bin/bash
function fun1 {
num1=$[var1*2]
}
read -p “input a num:” var1 fun1
echo the new value is: $num1
通过一个简单的例子感受一下函数的用法:
将之前写过的算数字总和和算奇数和偶数和的脚本融合在一个脚本中并用函数根据用户的输入来调用它们
#!/bin/bash
SUM (){
sum=0
read -p “计算1到几的和:” num
for i in seq $num
do
let sum=
i
+
i+
i+sum
let i++
done
echo $sum
}
oushu (){
sum=0
read -p “计算1到几的偶数和:” num
for i in seq $num
do
if [
(
(
i
l
e
t
s
u
m
=
((i%2)) -eq 0 ];then let sum=
((iletsum=i+$sum
fi
let i++
done
echo $sum
}
if [ $1 == SUM ];then
SUM
elif [ $1 == oushu ];then
oushu
else
echo “参数错误”
fi
函数的递归
函数自己调用自己的本身
列出目录内文件列表,目录用蓝色表示,文件显示层级关系
#!/bin/bash
list(){
for i in $1/*
do
if [ -d KaTeX parse error: Undefined control sequence: \e at position 27: … echo -e "\̲e̲[34mi\e[0m"
list $i " $2"
else
echo “
2
2
2i”
fi
done
}
list $1 $2
计算5的阶乘
#阶乘 5! 54321
#!/bin/bash
fa () {
if [
1
−
e
q
1
]
t
h
e
n
e
c
h
o
1
e
l
s
e
l
o
c
a
l
t
p
=
1 -eq 1 ] then echo 1 else local tp=
1−eq1]thenecho1elselocaltp=[
1
−
1
]
l
o
c
a
l
r
e
s
=
1 - 1] local res=
1−1]localres=(fa $tp)
echo $[ $1 * $res ]
5 * r e s ( 4 ∗ res(4* res(4∗res(3* r e s ( 2 ∗ res(2* res(2∗res(1))))
fi
}
5
fa 5 $1=5 tp=4 res=fa 4 echo 5 * fa 4 54321
fa 4 $1=4 tp=3 res=fa 3 echo 4 * fa 3 4321
fa 3 $1=3 tp=2 res=fa 2 echo 3 * fa 2 321
fa 2 $1=2 tp=1 res=fa 1 echo 2 * fa 1 21
fa 1 $1=1 echo 1
read -p “请输入:” num
res=$(fa $num)
echo $res
#!/bin/bash
function list_files()
{
for f in ls $1
;
do
if [ -d “
1
/
1/
1/f” ]; then
echo “
2
2
2f”
list_files “
1
/
1/
1/f” “$2”
else
echo “
2
2
2f”
fi
done
}
list_files “/var/log” “”