目录

  • 前言
  • 一、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 函数 与 函数库相关推荐

  1. 14.Linux shell编程(函数)

    (创建于2018/2/1) 1.简单的一个函数 1 #!/bin/bash 2 3 function myfunc{ //注意这里没有(),函数名何{之间没有空格导致出错,空格一定要有4 echo & ...

  2. Shell 语法之函数

    函数是被赋予名称的脚本代码块,可以在代码的任意位置重用.每当需要在脚本中使用这样的代码块时,只需引用该代码块被赋予的函数名称. 创建函数 格式 function name { commands } n ...

  3. shell基础07 函数

    1. 函数创建与使用 创建格式: function name {                                     name() { commands              ...

  4. 【WCE】Windows Shell 路径处理函数

    MSDN Library 上从未公布过 Windows Shell 路径处理函数的 Windows CE 实现信息.不过 $(_WINCEROOT)/PUBLIC/SHELL/OAK/LIB/$(_T ...

  5. shell中的函数shell中的数组告警系统需求分析

    2019独角兽企业重金招聘Python工程师标准>>> 20.16/20.17 shell中的函数 函数的概念 函数就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用 ...

  6. shell中的函数及脚本调试方法

    1.函数格式 目的:将一些相对对立的代码变成函数,提供可读性和重用性,避免重复编写相同代码. 函数格式: 函数关键字:function可以省略,可不带任何参数; 符号{表示函数体的开始(可在函数名后单 ...

  7. Shell编程基础---函数、数组

    2019独角兽企业重金招聘Python工程师标准>>> 本文索引: shell中的函数 shell中的数组 告警系统需求分析 shell中的函数 shell作为一种编程语言,必然有函 ...

  8. 20.17 shell中的函数

    2019独角兽企业重金招聘Python工程师标准>>> 20.17 shell中的函数 函数:就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用到这段代码时直接调用这 ...

  9. 【Android 逆向】ptrace 函数 ( C 标准库 ptrace 函数简介 | ptrace 函数真实作用 )

    文章目录 一.C 标准库 ptrace 函数简介 二.ptrace 函数真实作用 一.C 标准库 ptrace 函数简介 ptrace 函数 : 在 C 标准库 中有一个 ptrace 函数 , 该函 ...

最新文章

  1. neoterm如何安装python_NeoTerm下载-NeoTerm(安卓终端)下载v2.1.0-be8d6cf 安卓版-西西软件下载...
  2. ML之xgboost:利用xgboost算法(sklearn+GridSearchCV)训练mushroom蘑菇数据集(22+1,6513+1611)来预测蘑菇是否毒性(二分类预测)
  3. 初步认识Volatile-什么叫缓存一致性呢?
  4. qt中关于按钮的click()函数卓见
  5. c语言打印删除空格,新人提问:如何将输出时每行最后一个空格删除
  6. [OI学习笔记]最小生成树之Prim算法
  7. 如何使用@vue/cli 3.0在npm上创建,发布和使用你自己的Vue.js组件库
  8. Python complex()
  9. 拓端tecdat|R语言分位数回归、GAM样条曲线、指数平滑和SARIMA对电力负荷时间序列预测
  10. Webtrends网站运营分析解决方案简介
  11. ubuntu系统下抓取屏幕
  12. Factory模式(工厂模式)
  13. 华为鸿蒙和yunos,阿里的YunOS跟华为的鸿蒙差距大么?
  14. Python初级学习教程—从入门开始学习(函数、组合数据类型、文件操作、异常、模块)
  15. 如何理解垂直行业CRM?
  16. 数据科学行业已被挤爆?4点建议献给准备入行的小白
  17. 7-42 sdut-循环-3-评委评分(II)
  18. TAURUS GAME FINANCE(金牛游戏金融平台)3位一体综合性产业平台
  19. 面试常见问题:如何回答才得体?
  20. LINUX 降低密码复杂度,centos7 环境下修改root密码报错如下: BAD PASSWORD: it is too simplistic/systematic

热门文章

  1. 操作系统原理课程设计
  2. 安卓平板安装桌面linux,Android手机或平板电脑使用Linux桌面
  3. Mac电脑QQ输入两个短横(--)自动变成一个短横(——)----------小白的天堂
  4. AI作图在线软件怎么快速生成图片?只需要这3步!
  5. 智能车方向环pd控制理解
  6. MATLAB算法实战应用案例精讲-【连接分析】PageRank(补充篇)(附Python代码实现)
  7. 苹果库克赢得最佳CEO声誉的10个理由
  8. 人文地理学部分复习思考题答案
  9. 「从零单排canal 01」 canal 10分钟入门(基于1.1.4版本)
  10. 如何在Ubuntu上安装flash?