shell 函数 与 函数库
目录
- 前言
- 一、shell 函数
- 1.1 Shell函数定义
- 1.2 函数返回值
- 1.3 函数参数传值
- 1.4 函数变量生命周期
- 1.5 函数中可以调用函数
- 二、函数之递归
- 2.1 阶乘
- 2.2 遍历目录
- 2.2.1 方法一:递归输出目录名和文件名
- 2.2.2 方法二:递归输出绝对路径
- 2.2.3 递归输出 PATH 路径中的所有可执行文件
- 2.3 斐波那契数列
- 三、函数库
前言
使用函数是为了实现特定的功能,可以提高代码可读性、易维护、复用性。
一个函数可以被调用多次,不调用的话,函数中的命令不会执行。
一、shell 函数
- 将命令序列按格式写在一起;
- 方便重复使用命令块;
- 同一脚本文件中,函数体要写在调用函数行的上面;
- 函数在Shell脚本中仅在当前Shell环境中有效。
1.1 Shell函数定义
格式:function 函数名() {}或function 函数名 {}或函数名 ()
{}直接使用函数名访问函数
例:
#!/bin/bash
function fun1() { #定义一个函数fun1echo "这是函数fun1"
}fun1 #直接使用函数名执行函数#或result=`fun1 ` #将函数返回结果赋给一个变量,对这个变量进行操作
echo $result
1.2 函数返回值
return
表示退出函数并返回一个退出值,这个值是状态码,不是java中的字符串、集合等变量。脚本中可以用 $?
变量显示该值。
使用原则:
1、函数一结束就取返回值,因为 $?
变量只返回执行的最后一条命令的退出状态码;
2、$? 退出状态码必须是0~255,超出时值将取 除以256取余后的值。
#!/bin/bash
function fun1() {num=2return $[$num*2] #retuen 的状态只能用 echo $? 来获取值
}result=`fun1` #使用获取变量的方式获取不到return 的值
echo $result fun1 #执行函数
echo $? #获取return 的状态码result=`back` #将函数返回结果赋给一个变量,对这个变量进行操作
echo $result
1.3 函数参数传值
函数的括号中不需要写参数,直接通过 位置参数 和 函数的未知参数 进行传值与获取。
使用函数的位置变量,给函数参数赋值
# $1 获取 函数名后面的第一个参数
# $2 获取 函数名后面的第二个参数
# $3 .....
# .. .....function sum() {echo "$1+$2=$[$1+$2]" #first 就是 $1 参数、second就是 $2 参数
}read -p "输入第一个参数:" first
read -p "输入第二个参数:" second
sum $first $second
注:脚本文件的位置变量 和 函数名的位置变量 同时使用时并不冲突,别搞混了,按顺序来取 $1 $2 $3 …
1.4 函数变量生命周期
函数变量的作用范围:
- 函数在Shell脚本中仅在当前Shell环境中有效
- Shell 脚本中变量 默认全局有效
- 将变量限定在一个函数内部使用
local
命令
shell脚本 全局变量
function fun() {i=5echo $i
}
i=10 #两个i指向存储空间是一样的,修改一个另一个也会被修改
fun
echo $i#执行脚本结果
5
5
函数局部 local
function fun() {local i=5 #local 局部变量,和外面的i变量存储地址不同,互不影响echo $i
}
i=10 #全局变量
fun
echo $i#执行脚本结果
5
10
1.5 函数中可以调用函数
例1:
servicectl_usage ( ){echo "Usage:servicectl <service-name><start|stop|restart|reload|status>"return 1
}
chk_centos_ver() {grep "Centos.*release 7." /etc/centos-release &> /dev/null && echo "7"grep "Centos.*release 6." /etc/centos-release &> /dev/null && echo "6"grep "Centos.*release 5." /etc/centos-release &> /dev/null && echo "5"
}servicectl() {[[ -z $1 || -z $2 ]] && servicectl_usage[ $(chk_centos_ver)=="7" ] && systemctl $2 ${1}.service || service $1 $2
}
servicectl $1 $2#service httpd start
#systemctl start httpd
例2:
比如我文件 mytxt.txt 中有内容 param=10 param=20,
写个脚本文件如下内容,执行会输出 A B,但是我把 echo $ss
注释掉之后就不会输出,因为函数A调用函数B,函数B中的echo是把结果返回给函数A,自己并不输出信息到屏幕上,函数A获取后 就能用echo进行输出。
#!/bin/bash
function findvalue() {grep "param=10" /root/mytxt.txt &> /dev/null && echo "A"grep "param=20" /root/mytxt.txt &> /dev/null && echo "B"
}function servicectl() {ss=`findvalue`echo $ss
}#执行函数
servicectl
二、函数之递归
递归就是在函数A中再次调用函数A(自己调用自己)
使用递归注意点:
- 一定要有递归的操作(比如加减乘除)
- 执行递归函数前一定要小心排错,防止容易产生的死循环问题;
- 递归函数中每个循环选择语句如 if-elif-else 语句块只能有一个 echo 语句,没有条件块的最好用一个echo;
- 递归函数中的 echo 表示输出结果给上一级递归函数,不是输出到桌面
2.1 阶乘
#!/bin/bash
function Factorial() {if [ $1 -eq 1 ];thenecho 1 elsetemp=$[$1-1]echo $[$1*$(Factorial $temp)] #当前函数把执行结果 echo 给上一级函数, n*...*3*2*1 fi
}########### main () #############
read -p "请输入阶乘号:" n
total=$(Factorial $n)
echo $total
2.2 遍历目录
小知识:比如我们想从 PATH 路径下 寻找 所有可执行文件,我们可以这样通过 for 遍历去查询
#!/bin/bashIFS=$IFS:for folder in $PATH
doecho "-----------------$folder"f=`find $folder -type f`for file in $fdoif [ -x $file ];thenecho $file #查找可执行文件fidone
done
我们也可以使用 递归目录 的方式,去查询:
2.2.1 方法一:递归输出目录名和文件名
思路:给函数传入一个 绝对路径的目录名 参数,执行 ls 目录名
查询目录下所有目录和文件;
- 如果还是目录,则输出这个目录名,然后调用自身递归函数,继续 ls 遍历查询
- 如果是文件,则输出 文件名。
递归目录 调用递归函数传参时,必须为绝对路径
#!/bin/bashfunction listFiles(){for f in `ls $1` #ls遍历目录
doif [ -d "$1/$f" ];then #判断是否为目录echo "$2$f" #输出 目录名(第一次$2是空)listFiles "$1/$f" " $2" #再次调用递归函数ls 绝对路径目录名# $2是空格,每一级目录/文件比上一级目录/文件多个空格elseecho "$2$f" #输出 空格 文件名fi
done
}listFiles "/root/bin" ""
#listFiles "/root/myshell" "" 多测试几个目录
可使用 tree 目录名
命令验证结果
2.2.2 方法二:递归输出绝对路径
function listFiles(){for f in $1/* #ls遍历目录
doif [ -d $f ];then #判断是否为目录echo "$2$f" #输出 目录名(第一次$2是空)listFiles "$f" " $2" #再次ls 绝对路径目录名, $2是空格,每一集比上一级多个空格elseecho "--$2$f" #输出 -- 空格 文件名fi
done
}#listFiles"/var/log" ""
listFiles"/root/bin" ""
2.2.3 递归输出 PATH 路径中的所有可执行文件
#!/bin/bashfunction listFiles(){for f in $1/* #ls遍历目录
doif [ -d $f ];then #判断是否为目录echo "$2$f" #输出 目录名(第一次$2是空)listFiles"$f" " $2" #再次ls 绝对路径目录名, $2是空格,每一集比上一级多个空格elseecho "--$2$f" #输出 --空格 文件名fi
done
}############## main() ###########
IFS=$IFS:#for folder in `echo $PATH`
for folder in $PATH
doecho "-------------------------------$folder"listFiles $folder ""
done
sh 脚本名 | more
2.3 斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、…… 以此类推
斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)。
测试要求:用shell写个脚本文件,输入一个数 n( n>=2 ),输出 Fibonacci 数列的第 n 项,用递归函数实现。
比如输入 8,应该输出 13 (0 1 1 2 3 5 8 13 21 … )
代码:
#!/bin/bash
str=""
function fiboSeq(){if [ $1 -eq 1 ];then #第一个数为0echo 0elif [ $1 -eq 2 ];then #第一个数为1echo 1elsei=$[$1-1]j=$[$1-2]res=$[`fiboSeq $i` + `fiboSeq $j`] #递归调用进行相加echo $resfi
}########## main() ##########
read -p "输入斐波那契第几项:" n
result=`fiboSeq $n`
echo "斐波那契数列的第$n项为:"$result
验证:
此外还有“兔子繁殖”等问题可以用递归来做
三、函数库
创建函数库:
- 专门创建一个脚本文件,用作函数库,里面写的全是 一个个函数。
- 函数库中的函数可以执行特定的功能,可以返回,可以不返回信息,建议最起码得返回一个 return 0
脚本中使用函数库:
- 然后在 执行功能的脚本文件中使用
. 函数库脚本
或source 函数库脚本
, 加载(执行) 该函数库中的所有函数 - 函数库脚本名必须用绝对路径
- 不要有无异议的代码
如:
新增函数库文件 funhouse.sh,编辑
#!/bin/bash
#description: 函数库文件#两个数加法
function add(){echo $[$1+$2]
}function subtract(){echo $[$1-$2]
}function multiply_two(){echo $[$1*$2]
}#三个数乘法
function multiply_three(){echo $[$1*$2*$3]
}function divide(){if [ $2 -ne 0 ];then #除数不能为0echo $[$1 / $2]elseecho "除数不能为0"fi
}#阶乘函数
function Factorial(){if [ $1 -eq 1 ];thenecho 1else#local temp=$[$1-1]local temp=$(subtract $1 1) #用减法函数,并传参local result=$(Factorial $temp)#echo $[$1*$result]echo $(multiply_two $1 $result) #用乘法函数,并传参fi
}
在脚本文件中 txt.sh 编辑
#!/bin/bash
#description: 函数库文件###main####
. /root/funhouse.sh #加载函数库文件#下面就可以直接使用函数库文件中的函数value1=12
value2=6jia=`add $value1 $value2`echo "加法 $value1+$value2="$jiaecho '乘法 2*3*2='`multiply_three 2 3 2`echo '除法 2/0='`divide 2 0`
echo '除法 12/6='`divide 12 6`echo '5的阶乘='`Factorial 5`
验证:
shell 函数 与 函数库相关推荐
- 14.Linux shell编程(函数)
(创建于2018/2/1) 1.简单的一个函数 1 #!/bin/bash 2 3 function myfunc{ //注意这里没有(),函数名何{之间没有空格导致出错,空格一定要有4 echo & ...
- Shell 语法之函数
函数是被赋予名称的脚本代码块,可以在代码的任意位置重用.每当需要在脚本中使用这样的代码块时,只需引用该代码块被赋予的函数名称. 创建函数 格式 function name { commands } n ...
- shell基础07 函数
1. 函数创建与使用 创建格式: function name { name() { commands ...
- 【WCE】Windows Shell 路径处理函数
MSDN Library 上从未公布过 Windows Shell 路径处理函数的 Windows CE 实现信息.不过 $(_WINCEROOT)/PUBLIC/SHELL/OAK/LIB/$(_T ...
- shell中的函数shell中的数组告警系统需求分析
2019独角兽企业重金招聘Python工程师标准>>> 20.16/20.17 shell中的函数 函数的概念 函数就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用 ...
- shell中的函数及脚本调试方法
1.函数格式 目的:将一些相对对立的代码变成函数,提供可读性和重用性,避免重复编写相同代码. 函数格式: 函数关键字:function可以省略,可不带任何参数; 符号{表示函数体的开始(可在函数名后单 ...
- Shell编程基础---函数、数组
2019独角兽企业重金招聘Python工程师标准>>> 本文索引: shell中的函数 shell中的数组 告警系统需求分析 shell中的函数 shell作为一种编程语言,必然有函 ...
- 20.17 shell中的函数
2019独角兽企业重金招聘Python工程师标准>>> 20.17 shell中的函数 函数:就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用到这段代码时直接调用这 ...
- 【Android 逆向】ptrace 函数 ( C 标准库 ptrace 函数简介 | ptrace 函数真实作用 )
文章目录 一.C 标准库 ptrace 函数简介 二.ptrace 函数真实作用 一.C 标准库 ptrace 函数简介 ptrace 函数 : 在 C 标准库 中有一个 ptrace 函数 , 该函 ...
最新文章
- neoterm如何安装python_NeoTerm下载-NeoTerm(安卓终端)下载v2.1.0-be8d6cf 安卓版-西西软件下载...
- ML之xgboost:利用xgboost算法(sklearn+GridSearchCV)训练mushroom蘑菇数据集(22+1,6513+1611)来预测蘑菇是否毒性(二分类预测)
- 初步认识Volatile-什么叫缓存一致性呢?
- qt中关于按钮的click()函数卓见
- c语言打印删除空格,新人提问:如何将输出时每行最后一个空格删除
- [OI学习笔记]最小生成树之Prim算法
- 如何使用@vue/cli 3.0在npm上创建,发布和使用你自己的Vue.js组件库
- Python complex()
- 拓端tecdat|R语言分位数回归、GAM样条曲线、指数平滑和SARIMA对电力负荷时间序列预测
- Webtrends网站运营分析解决方案简介
- ubuntu系统下抓取屏幕
- Factory模式(工厂模式)
- 华为鸿蒙和yunos,阿里的YunOS跟华为的鸿蒙差距大么?
- Python初级学习教程—从入门开始学习(函数、组合数据类型、文件操作、异常、模块)
- 如何理解垂直行业CRM?
- 数据科学行业已被挤爆?4点建议献给准备入行的小白
- 7-42 sdut-循环-3-评委评分(II)
- TAURUS GAME FINANCE(金牛游戏金融平台)3位一体综合性产业平台
- 面试常见问题:如何回答才得体?
- LINUX 降低密码复杂度,centos7 环境下修改root密码报错如下: BAD PASSWORD: it is too simplistic/systematic
热门文章
- 操作系统原理课程设计
- 安卓平板安装桌面linux,Android手机或平板电脑使用Linux桌面
- Mac电脑QQ输入两个短横(--)自动变成一个短横(——)----------小白的天堂
- AI作图在线软件怎么快速生成图片?只需要这3步!
- 智能车方向环pd控制理解
- MATLAB算法实战应用案例精讲-【连接分析】PageRank(补充篇)(附Python代码实现)
- 苹果库克赢得最佳CEO声誉的10个理由
- 人文地理学部分复习思考题答案
- 「从零单排canal 01」 canal 10分钟入门(基于1.1.4版本)
- 如何在Ubuntu上安装flash?