shell脚本学习之基础篇五:函数

函数的作用

在编写shell脚本的时候,经常会发现在多个地方使用了同一段代码,如果只是一小段代码,一般也无关紧要,但是要在脚本中多次重写大块代码的话就太累了,shell中的函数就可以解决这个问题,可以将代码放进函数体封装起来,在需要的地方直接调用它就可以了,它可以提高脚本的可读性和重用性。

函数的定义

定义函数的几种方式:

function 函数名(){
command
}       //这是一种规范写法
function 函数名 {   //没有括号的话一定要空格否则会报错
command
}
函数名(){
command
}

要么使用function定义函数,要么就要使用()来定义函数,不能两个都没有!
函数的名称必须是唯一的!如果重名了,相当于你重新定义了函数,会覆盖之前函数的内容。

函数的调用

要在脚本中使用函数,只需要直接指定函数名就可以了,可以在脚本中的任意位置定义函数,不一定要在脚本开头。

[root@server myscripts]# vim fun.sh



#!/bin/bash
function fun1(){
echo "this is a function!"
}

fun1    //直接写函数名就会运行函数体内的代码

[root@server myscripts]# . fun.sh
this is a function!

在脚本中调用另一个脚本中定义的函数:在脚本中source一下另一个脚本的路径就可以直接调用了

[root@server myscripts]# vim hello.sh 

#!/bin/bash
function hello(){

        echo "hello"
        echo "world"
}
[root@server myscripts]# vim fun.sh 

#!/bin/bash
function fun1(){
echo "this is a function!"
}

fun1

source /opt/myscripts/hello.sh

hello

[root@server myscripts]# . fun.sh 
this is a function!
hello
world

也可以把函数的输出赋值给变量使用,用反撇号``引起来

[root@server myscripts]# vim fun1.sh

#!/bin/bash
function db1(){
read -p "enter a value: " value
echo $[$value*2]
}
new=`db1`
echo "the new value is $new"

[root@server myscripts]# . fun1.sh
enter a value: 12
the new value is 24

函数的返回值

默认情况下,函数的退出状态码是函数中最后一条命令返回的退出状态码,在函数执行结束后,可以用标准变量$?来确定函数的退出状态码

[root@server myscripts]# . fun.sh 
this is a function!
[root@server myscripts]# echo $?
0

$?只会对函数返回的最后一条命令的执行状态做判断,成功就为0,失败就返回一个非0值,然而没有办法进行判断为什么失败,哪里失败了,这时候就可以用到return命令,他可以指定一个整数值来定义函数的退出状态码,我们可以根据给定的状态码分析函数的执行结果,这个整数值在0-255之间,如果定义return的值超过了255,他返回的就是一个错误的返回值

[root@server myscripts]# vim fun1.sh

#!/bin/bash
function db1(){
read -p "enter a value: " value
echo "doubling the value"
return $[$value*2]
}
db1
echo "the new value is $?"   //这里的$?返回的就不是0和非0值了而是return的值

[root@server myscripts]# . fun1.sh
enter a value: 10
doubling the value
the new value is 20

如果在$ ?之前执行了其他命令的话,它就不会返回return的值,而是返回上一条命令执行的返回码,下面这个例子在之前的脚本基础上,在调用了db1函数之后又执行了echo "hello"命令,这个命令是成功的,所以最后$?的返回码是0

[root@server myscripts]# vim fun1.sh

#!/bin/bash
function db1(){
read -p "enter a value: " value
echo "doubling the value"
return $[$value*2]
}
db1
echo "hello"
echo "the new value is $?"

[root@server myscripts]# . fun1.sh
enter a value: 12
doubling the value
hello
the new value is 0

对于以下这个脚本来说,它的函数是sum,这个函数的结果是用户输入的2个数字的总和
但是它的返回码却是100
所以$?返回的是返回码
$number的值就是函数体的值

[root@server myscripts]# vim fun3.sh

#!/bin/bash
sum(){
read -p "请输入第一个整数:" num1
read -p "请输入第二个整数:" num2
SUM=$[$num1+$num2]
echo $SUM
return 100
}
number=`sum`
echo $?
echo $number

[root@server myscripts]# . fun3.sh 
请输入第一个整数:2
请输入第二个整数:5
100
7

看下面这个例子,return还可以当做结束函数使用,一个函数运行到return的时候就不会再往下运行了
另外,我们定义了hello这个函数,但是我们并没有调用它,直接退出脚本,在命令行source一下就可以直接使用了

[root@server myscripts]# vim hello.sh 

#!/bin/bash
function hello(){

        echo "hello"
        return
        echo "world"
}

[root@server myscripts]# source hello.sh 
[root@server myscripts]# 
[root@server myscripts]# hello
hello

函数的传参

现在要实现一个功能:运行脚本,将第一个参数和第二个参数相加的总和输出,这里可以通过位置参数$n来向脚本里的函数传递参数

[root@server myscripts]# vim fun2.sh

#!/bin/bash
function add(){7
sum=$[$1+$2]
echo $sum
}
add $1 $2  //调用函数的时候别忘记后面加上传递的参数

[root@server myscripts]# . fun2.sh 4 5
9

也可以用以下方式传参,测试某个文件是否存在,函数体外先定义一个变量然后函数体内引用这个变量

[root@server myscripts]# vim fun4.sh

#!/bin/bash
file=/etc/fff
function test_file(){
if [ -f $file ];then
return 100
else
return 200
fi
}
test_file
echo $?

[root@server myscripts]# . fun4.sh 
200

看下面的例子,传参的时候注意区分函数的参数和脚本的参数!!!

[root@server myscripts]# vim canshu.sh

#!/bin/bash
test1(){
        echo $1
}

test2(){
        echo $1
}

test3(){
        echo $1
}

test1 $1   //位置1的参数是相对于脚本来说的,他会把这个参数传递给函数test1,他对于test1来说是$1
test2 $2   //位置2的参数是相对于脚本来说的,他会把这个参数传递给函数test2,他对于test2来说是$1
test3 $3
     
[root@server myscripts]# . canshu.sh apple banana orange
apple
banana
orange

函数中的变量

函数体中会引用两种变量类型:全局变量和局部变量
全局变量:对整个脚本有效,也对函数体有效,只要是在脚本中定义的就是全局变量
局部变量:只对函数体有效,要用local关键字定义,在脚本中不识别

看下面的例子,定义了一个全局变量a和一个局部变量b,观察脚本输出结果

[root@server myscripts]# vim fun5.sh

#!/bin/bash
a=1   //函数体外定义的是全局变量
function test1(){
local b=2   //函数体内用local定义的是局部变量,只对函数体有效
}

test1
echo $a
echo $b

[root@server myscripts]# . fun5.sh  //所以这里只输出了a的值
1

修改b为全局变量之后,观察脚本输出结果

[root@server myscripts]# vim fun5.sh

#!/bin/bash
a=1
function test1(){
b=2   //虽然b是在函数体内定义的,但是它没有local关键字,所以它也是全局变量
}

test1
echo $a
echo $b

[root@server myscripts]# . fun5.sh   //所以这里a和b都是全局变量,脚本可以读到
1
2

函数的递归

递归就是定义函数的时候自己调用自己,看下面的例子,遍历/var/log目录下的所有文件并且直观的显示出来

[root@server myscripts]# vim digui.sh 

#!/bin/bash
function list(){
        for f in `ls $1`  //先查看/var/log下面的文件
        do
          if [ -d "$1/$f" ];then   //如果这是个目录,则打印出来
            echo "$1/$f"
            list "$1/$f" " $2"  //然后继续调用这个函数查看文件判断文件
          else
            echo "$2/$f"  //如果不是目录的话,直接空格打印出来,空格的作用只是为了显示层级
          fi

        done
}

list "/var/log" ""

[root@server myscripts]# . digui.sh 
/var/log/anaconda
 /anaconda.log
 /ifcfg.log
 /journal.log
 /ks-script-nNVdDg.log
 /packaging.log
 /program.log
 /storage.log
 /syslog
 /X.log
/var/log/audit
 /audit.log
 /audit.log.1
/boot.log
/boot.log-20200715
/boot.log-20200716
……

猜你喜欢

转载自blog.csdn.net/shengjie87/article/details/107528397
今日推荐