马哥学习---李洋个人笔记-----函数

函数
函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程 它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序 的一部分
函数和shell程序比较相似,区别在于:  Shell程序在子Shell中运行  而Shell函数在当前Shell中运行。因此在当前Shell中,函数可以对shell中变量进行修改
函数的命名方式,通常不使用已定义的别名,或命令来当函数的名字,因为函数的优先级非常高。比如使用ls当函数名,那么当函数运行后,再敲ls不会显示文件了,而是取决于函数当中的函数体。函数命名方式(最通用的):系统自带函数默认带下划线。
函数名 (){
函数体
}
的形式来命名,两种括号之间没有空格,如果函数体中包含有当前shell已被定义的变量,最好在定义的变量前加上local 避免干扰报错,例子

函数(){ ----------------------------定义一个实现打印 name=李洋的函数

name=李洋

echo “函数:$name”

} ------------------------- 定义完成

name= 黄乐颖 -------------------------- 又定义name=黄乐颖

ecnho $name ---------------------------打印变量$name

李洋 由此可以看出,函数的判定高于变量。

为了避免这种冲突,我们在函数体中加入 local就可以避免这种情况了。

函数(){

local name=李洋 ---------------------- 前面加上了local

echo “函数:$name”

}

name= 黄乐颖

黄乐颖 ------------------------- 不在影响变量了

函数的定义和使用:
– 可在交互式环境下定义函数,即命令行下定义函数,但是这两样的函数只在本次登录的的shell中生效,不会永久生效,当前用户退出则函数丢失。

– 可将函数放在脚本文件中作为它的一部分
而放入脚本中的函数,想在脚本内部使用的话,必须先定义,再调用。

– 可放在只包含函数的单独文件中

调用:函数只有被调用才会执行 调用格式:
函数名 (函数名出现的地方,会被自动替换为函数中的代码 )像命令一样使用,也可以自定义一些参数选项。比如写一个脚本:
#1 /bin/bash

redyel(){

if [ "$1" = "-r" ];then echo -e "\033[1;41m \033[1;43m \033[0m";return;fi

echo -e "\033[1;43m \033[1;41m \033[0m"

}

redyel

redyel –r

加入一个判断项目,就可以像执行命令一样来使用函数了。 比如执行完这个脚本后,我们在命令行单独输入

redyel 就会看到×××和红色的方块。

而想调用多个函数的文件,假设脚本名字为yanse.sh,那么在命令行输入点+空格+yanse.sh 就可以看到由黄红,红黄组成的颜色小方块了。

函数的生命周期:被调用时创建,返回时终止

函数有两种返回值:
1 函数的执行结果返回值:
(1) 使用echo等命令进行输出
在函数尾部加入 echo 数字(假设为3) ,然后执行完函数后,在命令行输入
echo 函数名 ,那么显示的值就为3.例如

add (){ c=$[3+3]; echo $c; } 打印出来$c的值为6,但是在执行函数中不会显示,而是把这个值赋给函数本身,

add 查看这个函数的值

6 值为6.

(2) 函数体中调用命令的输出结果

add (){ c=$[3+3]; echo $c; return 10;}

这时候add的值依然为6,但是echo $?的值已经被 return 改为了10.

2 函数的退出状态码:
(1) 默认取决于函数中执行的最后一条命令的退出状态码

(2) 自定义退出状态码,其格式为:

return 从函数中返回,用最后状态命令决定返回值

return 0 无错误返回。

return 1-255 有错误返回

在函数中任意位置插入return就相当于结束这个函数。

使用函数文件
1 文件名可任意选取,但最好与相关任务有某种联系。例如: functions.main
2 可以将经常使用的函数存入函数文件,然后将函数文件载入shell
3 一旦函数文件载入shell,就可以在命令行或脚本中调用函数。可以使用 set命令查看所有定义的函数,其输出列表包括已经载入shell的所有函 数
4 若要改动函数,首先用unset命令从shell中删除函数。避免出现冲突。改动完毕后,再重新载入此文件。
5 一般函数只会在当前shell中生效,若想全局都生效,可以使用export命令来实现。 # export –f 函数名 可以将指定函数变为全局函数(一般不这么用,函数通常都是引用的方式,定义了函数后,在其他脚本中使用直接 函数名 即可 )

函数递归
用来实现函数自身调用自身的方式。举例:

vim hanshu.sh

!/bin/bash

fact() {

if [ $1 -eq 0 -o $1 -eq 1 ]; then

echo 1

else

echo $[$1*$(fact $[$1-1])] fi

}

fact $1

这个例子中,是实现阶乘的方式。(一个正整数的阶乘,是所有小于及等于该数的正整数的积,并且有0的阶乘为1,自然数n的 阶乘写作n!),n!=1×2×3×...×n
在上例中,假设n的值为10,由函数生命周期可知,起始于$1值为10的时候,终止于$1值为1的时候。因为值不为1的时候,因为条件不满足,所以不停的被调用自身,当值为1的时候,开始输出并返回值。函数的生命周期:被调用时创建,返回时终止.
$[$1*$(fact $[$1-1])] 当中:

中括号部分,即$[$1-1]是取值$1-1后的值。

小括号部分fact $[$1-1]是函数调用时,每一次去判断条件时所用的值。

大括号部分[$1*$(fact $[$1-1])]则是用$1的值,乘以自身-1后的值。

设$1为10,那么这里的运算式可以看做 10*9
使用命令 bash –x +函数名来查看详细执行过程

  • fact 10-------------------------------------------当值为10的时候
  • '[' 10 -eq 0 -o 10 -eq 1 ']'--------------------10不满足条件,执行else部分
    ++ fact 9---------------------------------减1后值为9,再次调用函数去执行if判断部分
    ++ '[' 9 -eq 0 -o 9 -eq 1 ']'----------------------依然不满足条件
    +++ fact 8-------------------------------减1后值为8,再次调用函数去执行if判断部分
    +++ '[' 8 -eq 0 -o 8 -eq 1 ']'--------------------依然不满足条件
    ++++ fact 7-----------------------------减1后值为7,再次调用函数去执行if判断部分
    ++++ '[' 7 -eq 0 -o 7 -eq 1 ']'------------------依然不满足条件
    +++++ fact 6---------------------------减1后值为6,再次调用函数去执行if判断部分
    +++++ '[' 6 -eq 0 -o 6 -eq 1 ']'----------------依然不满足条件
    ++++++ fact 5-------------------------减1后值为5,再次调用函数去执行if判断部分
    ++++++ '[' 5 -eq 0 -o 5 -eq 1 ']'---------------依然不满足条件
    +++++++ fact 4-----------------------减1后值为4,再次调用函数去执行if判断部分
    +++++++ '[' 4 -eq 0 -o 4 -eq 1 ']'--------------依然不满足条件
    ++++++++ fact 3---------------------减1后值为3,再次调用函数去执行if判断部分
    ++++++++ '[' 3 -eq 0 -o 3 -eq 1 ']'------------依然不满足条件
    +++++++++ fact 2--------------------减1后值为2,再次调用函数去执行if判断部分
    +++++++++ '[' 2 -eq 0 -o 2 -eq 1 ']'-----------依然不满足条件
    ++++++++++ fact 1------------------减1后值为1,再次调用函数去执行if判断部分
    ++++++++++ '[' 1 -eq 0 -o 1 -eq 1 ']'---------满足条件,开始输出
    ++++++++++ echo 1----------------值为1时,所返回的值。这个1是then返回的。
    +++++++++ echo 2------------------值为2时,所返回的值。21的值
    ++++++++ echo 6--------------------值为3时,所返回的值。3
    21的值
    +++++++ echo 24--------------------值为4时,所返回的值。4
    321的值
    ++++++ echo 120--------------------值为5时,所返回的值。5….1的值
    +++++ echo 720----------------------值为6时,所返回的值。6…..
    1的值
    ++++ echo 5040----------------------值为7时,所返回的值。7……. 1的值
    +++ echo 40320----------------------值为8时,所返回的值。8…..
    1的值
    ++ echo 362880----------------------值为9时,所返回的值。9….. *1的值
  • echo 3628800----------------------值为10时,所返回的值。10….. *1的值
    3628800--------------------输出取值为10时候,函数的值。是由else当中的echo来输出的。

    由上面分析可以看出,每一次判断后,都会把原本要产生的值存起来,接着去调用函数来判断,然后当条件满足时,反过来(从10开始判断,从1开始计算)计算产生的值。最终用echo来输出最终值。

    也就是说,当$1的值为1的时候,函数满足了输出条件。开始反向计算之前,条件不满足,所欠的(保存的)值一一计算出来并返回。
    也可以理解为,当$1的值为1时候,函数计算出来值。有了1的值,就可以去计算2的值,然后有了2的值,就可以去计算3的……直到最后计算完。

猜你喜欢

转载自blog.51cto.com/13477118/2132398
今日推荐