shell脚本编程进阶:函数

一、函数介绍

函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程;
它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分;
函数和shell程序比较相似,区别在于:
(1)Shell程序在子Shell中运行;
(2)Shell函数在当前Shell中运行;因此在当前Shell中,函数可以对shell中变量进行修改;

例如:
脚本1:clean.sh:rm -rf /app/x/*
脚本2:f1.sh:
#!/bin/bash
echo f1.sh
/app/bin/clean.sh(bash调用)

二、定义函数

定义函数=定义别名;
建议不要用与系统cmd相同的函数名;
企业规范函数命名:f_name 或者 func_name;

declear -f f_name  查看某个函数
declear -f   查看所有函数
declear -x   查看所有环境变量
unset f_name  取消(删除)函数
函数(两部分组成):函数名和函数体;
help function

语法一:
function f_name {
       ...函数体...
}

语法二:
function f_name(){
      ...函数体...
}

语法三:(建议)
f_name(){
      ...函数体...
}

注意:
function f_name(){ cmd; }  
不换行——必须加 ;和 “空格”(中括号里);

例如:
function clean () { echo clean1;echo clean2; }
clean
unset clean

三、函数的定义和使用

1.函数——声明、定义;函数生效——调用;(先定义,后调用)
2.函数只有被调用才会执行;
3.调用方法:给定函数名;
4.函数名出现的地方,会被自动替换为函数代码;
5.函数的生命周期:被调用时创建,返回时终止;
(1)交互式环境下定义函数;(类似cat)
f_name {
>...
>... 
>}
(2)将函数放在脚本文件中作为它的一部分;
在脚本前面先定义函数;然后在调用函数;只适用于自己使用;
#!/bin/bash
f_name {
    echo f_name
}
f_name
(3)放在只包含函数的单独文件中;(可以被其他文件调用)
系统定义的函数都放在这个文件:cat /etc/init.d/functions;
grep '^.*().*' /etc/init.d/functions|wc -l  统计函数库中函数个数
自己可以定义:vim functions    (定义函数的文件,可以不写shebang机制)
f_name1 {
    echo f_name
}
f_name2 {
    echo f_name
}

例如:testfuc.sh
#!/bin/bash
. /app/bin/functions    (调用函数库)
echo cmd1    (脚本自己的程序)
f_name1    (调用的函数)
f_name2    (调用的函数)

四、函数返回值(两种)

1.函数的执行结果返回值
(1)使用echo等命令进行输出;
(2)函数体中调用命令的输出结果;
2.函数的退出状态码
(1)默认取决于函数中执行的最后一条命令的退出状态码;
(2)自定义退出状态码,其格式为:
return  从函数中返回,用最后状态命令决定返回值
return 0  无错误返回
return 1-255  有错误返回
例1
vim functions
func1 {
      echo 100
}
func2 {
      echo func2-cmd1
      return(100或者exit)
      echo func2-cmd2
}

. functions  使系统里有缓存(如果更改functions文件,需要重新使其重新生效,就执行此操作)
func1:100  使系统里有缓存
let i=`func1`+200  `func1`可被其他命令调用(即:当做别名使用)
echo $i:300
func2:(1)return:退出函数;(2)exit:退出脚本;

例2
vim testfunc.sh
. /app/bin/functions(例1中的functions库)
func2  (例1中的func2)
echo continue

testfunc.sh(运行)
(1)return:退出函数;func2-cmd1  continue
(2)exit:退出脚本;func2-cmd1

例3
vim testfunc.sh
. /app/bin/functions(例1中的functions库)
func2  (例1中的func2)
echo $?    return 显示:0(真);return 100 显示:100(假);
echo continue

五、使用函数文件

1.可以将经常使用的函数存入函数文件,然后将函数文件载入shell;
2.文件名可任意选取,但最好与相关任务有某种联系;例如:functions.main;
3.一旦函数文件载入shell,就可以在命令行或脚本中调用函数;
set  查看所有定义的函数,其输出列表包括已经载入shell的所有函数;
4.若要改动函数,首先用unset命令从shell中删除函数;改动完毕后,再重新载入此文件;
国际象棋(思路)
red(){ echo -e '\033[41m \033[0m'; };red
red;red;red;red
yellow(){ echo -e '\033[43m \033[0m'; };yellow
yellow;yellow;yellow;yellow
red;red;red;red;yellow;yellow;yellow;yellow

六、函数参数

cat /etc/init.d/sshd
脚本调用参数
(空格)/etc/init.d/sshd status
(空格)/etc/init.d/sshd restart

1.函数可以接受参数

(1)传递参数给函数
调用函数时,在函数名后面以空白分隔给定参数列表即可;
例如:“testfunc arg1 arg2 ...”;
(2)在函数体中,
使用 $1, $2, ...调用这些参数;还可以使用 $@, $*, $# 等特殊变量;
例
(1)vim functions
func {
      echo 1st is $1
      echo 2st is $2
      echo all args are $*
      echo the arg numbers is $#
      echo funcname is $0
}
max {
      [ $1 -gt $2 ] && echo max is $1 || echo max is $2
}

(2)testfunc1.sh
. /app/bin/functions
func a b c
echo continue

(3)testfunc2.sh
. /app/bin/functions
max 10 20
echo continue
(4). functions  更改functions文件,需要重新使其重新生效

2.函数变量

变量作用域
(1)环境变量:当前shell和子shell有效;
(2)本地变量:只在当前shell进程有效,为执行脚本会启动专用子shell进程;作用范围是当前shell脚本程序文件,包括脚本中的函数;
(3)局部变量:函数的生命周期;函数结束时变量被自动销毁;
(4)注意:如果函数中有局部变量,如果其名称同本地变量,使用局部变量
(5)在函数中定义局部变量的方法
local NAME=VALUE
使用脚本中定义的变量(最好加上括号)
(1)vim functions
func () {
      (var=fuc)函数是否定义变量
      echo $var
      echo func-cmd1
      return 100
      echo func-cmd2
}
(2)vim testfunc.sh
. /app/bin/functions
var=testfunc
func
echo continue

(3). functions  更改functions文件,需要重新使其重新生效
(4)testfunc.sh
函数未定义变量:testfunc func-cmd1 continue
函数定义变量:func func-cmd1 continue
变量名相同时,函数里的变量可以更改脚本中的变量;所以尽量避免变量名称相同(防止混乱);
local NAME=VALUE  此变量只在函数中有效
为了区分,可以统一变量名:local local_NAME=VALUE
步骤1:vim functions
func () {
      local var=fuc
      echo $var
      echo func-cmd1
      return 100
      echo func-cmd2
}

步骤2:vim testfunc.sh
. /app/bin/functions
var=testfunc
echo var=$var
func
echo var=$var
echo continue

步骤3:. functions  更改functions文件,需要重新使其重新生效

步骤4:bash testfunc.sh

七、函数递归

函数递归:函数直接或间接调用自身;注意递归层数;

n!=1×2×3×...×n
n!=(n-1)!×n
n!=(n-2)!×(n-1)×n
vim fact.sh
#!/bin/bash
fact () {
    if [ $1 -eq 0 -o $1 -eq 1 ]; then
    echo 1
    else
    echo $[$1*$(fact $[$1-1])]
fi
}
fact $1(调用自己+参数)

执行操作
fact.sh 10
fact.sh -1  死循环;直至资源耗尽;
killall fact.sh  
pstree -p  保留原来状态(进程),循环下一个状态(进程);
ps auxf|less
linux递归函数调用,嵌套深度无限制;编写脚本时,要注意合理利用函数调用;
Paste_Image.png

fork炸弹

1.fork炸弹
一种恶意程序,它的内部是一个不断在fork进程的无限循环,实质是一个简单的递归程序;
由于程序是递归的,如果没有任何限制,这会导致这个简单的程序迅速耗尽系统里面的所有资源;
2.函数实现
:() { :|:& };:
bomb() { bomb | bomb & }; bomb
3.脚本实现
cat bomb.sh
#!/bin/bash
./$0|./$0&

八、匿名函数和环境函数

匿名函数:{ cmd1;cmd2 }
环境函数
(1)定义函数;
(2)declare -fx 或 export -f  声明环境函数;
(3)调用;
让子进程继承父进程的函数;
Paste_Image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容