shell函数

77 篇文章 0 订阅
15 篇文章 1 订阅

1.shell函数概述

1.1 shell函数定义

函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程,它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分。

函数和shell程序区别

  • shell程序在子shell中运行

  • 函数在当前Shell中运行。因此在当前Shell中,函数可对shell中变量进行修改

shell函数:

使用函数可以避免代码重复

使用函数可以将大的工程分割为若干小的功能模块,代码的可读性更强

shell函数定义:

格式一:

function 函数名  {
	命令序列
}

格式二:

函数名 (){
	命令序列
}

查看函数

# 查看当前已定义的函数名 
declare -F 
# 查看当前已定义的函数定义 
declare -f 
# 查看指定当前已定义的函数名 
declare -f func_name 
# 查看当前已定义的函数名定义 
declare -F func_name

在这里插入图片描述

1.2 函数返回值

return表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值

使用原则:
(1) 函数一结束就取返回值,因为$?变量只返回执行的最后一条命令的退出状态码
(2) 退出状态码必须是0~255,超出时值将为除以256取余

函数的执行结果返回值:

使用echo等命令进行输出

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

函数的退出状态码:

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

自定义退出状态码,其格式为:
在这里插入图片描述
在这里插入图片描述

[root@clr /opt/mywork]# vim 20.sh

#!/bin/bash

function test01 {
  read -p "请输入一个整数:" num
  return  $[num *2]
}

test01
echo $?
~              

1.3 函数变量的作用范围

  • 函数默认只能在脚本内的shell环境有效(使用source执行脚本,也公影响系统当前的shell环境)
    在这里插入图片描述

  • 脚本中的变量默认全局有效(即函数体内外都有效)

在这里插入图片描述

[root@clr /opt/mywork]# vim 2.sh

#!/bin/bash

myfun() {
  echo $name

  name=lisi

  echo $name

  name=zhangsan
}


#####main######

myfun

echo $name
  • 在函数体内执执行local 变量,可将变量限定在函数体内部使用,即local定义的变量值只能在函数体内部使用,出了函数体将无法使用

在这里插入图片描述

[root@clr /opt/mywork]# vim 2.sh

#!/bin/bash

myfun() {
  echo $name

  local name=lisi

  echo $name

}

#####main######

name=zhangsan
myfun

echo $name

2. 函数的调用

函数的调用方式

  • 可在交互式环境下定义函数

  • 可将函数放在脚本文件中作为它的一部分

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

调用:==函数只有被调用才会执行,通过给定函数名调用函数(==直接执行函数名即可,不需要带小括号),函数名出现的地方,会被自动替换为函数代码

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

在这里插入图片描述

[root@clr /opt/mywork]# vim 1.sh

#!/bin/bash

#定义函数
sum2() {
  #函数体内部的$1 $2 代表的是调用函数时,函数后面跟的位置参数
  sum=$[$1 - $2 ]
  echo $sum
sum2() {
  #函数体内部的$1 $2 代表的是调用函数时,函数后面跟的位置参数
  sum=$[$1 - $2 ]
  echo $sum
  echo "在函数体内部的\$#代表调用函数时,函数后面跟的参数个数,当前>函数后面有$#个参数"
  echo "在函数体内部的\$@代表调用函数时,函数后面跟的所有参数,当前>函数后面的参数有:$@"
  echo "在函数体内部,\$0代表当前脚本$0"
}

echo "在函数体外时,\$#代表脚本后面跟的参数个数,当前脚本后面有$#个>参数"
echo "在函数体外时,\$@代表脚本后面跟的所有参数,当前脚本后面参数有>:$@"
echo "在函数体外,\$0代表当前脚本$0"

#调用函数
#函数体外的$1 $2 代表的是执行脚本时,脚本后面跟的位置参数
sum2 $2 $1

3. 函数的递归

递归

函数调用自己本身的函数

递归调用,实现阶乘的计算;

在这里插入图片描述

[root@clr /opt/mywork]# vim 3.sh

#!/bin/bash
#使用函数的递归实现阶乘

fact() {
  if [ $1 -eq 1 ];then
    echo 1
  elif [ $1 -gt 1 ];then
    local tmp=$[$1 - 1]
    local res=$(fact $tmp)  #在函数内调用函数
    echo $[$1 * res]
  else
    echo "输入的值无效。请输入大于等于1的整数!"
  fi
}

#####main#####

read -p "请输入一个大于等于1的整数:" num
res=$(fact $num)
echo "$num的阶乘值为$res"

例题演练一:
(1)使用函数递归目录/var/log,如果是文件直接输出文件名,如果是目录>则输出目录名且输出此目录下的所有目录和文件名;

在这里插入图片描述

[root@clr /opt/mywork]# vim 4.sh

#!/bin/bash
#使用函数递归目录/var/log,如果是文件直接输出文件名,如果是目录>则输出目录名且输出此目录下的所有目录和文件名

listf () {
  for f in $(ls $1)
  do
    if [ -d "$1/$f" ];then
      echo "$2目录$f"
      listf "$1/$f" "  $2"
    else
      echo "$2文件$f"
    fi

  done

}


#listf $(/var/log) $()
listf  "/var/log" $()

例题演练二:
(2)通过脚本输出环境变量PATH所包含的所有目录以及其中的子目录和所有不可执行文件;

在这里插入图片描述

[root@clr /opt/mywork]# vim 5.sh
#!/bin/bash
#通过脚本输出环境变量PATH所包含的所有目录以及其中的子目录和所有不可执行文件

#定义一个遍历PATH环境变量的函数
list_path() {
    IFSB=$IFS
    IFS=$IFS':'
    for F in $PATH
    do
        echo "$F"
    done
    IFS=$IFSB
}

#定义一个递归函数
listf() {
    for F in $(ls $1)
    do
        if [ -d "$1/$F" ];then
            echo "$2$F"
            listf "$1/$F" "  $2"
        else
            if [ ! -x "$1/$F" ];then
                echo "$2$F"
            fi
        fi
    done
}

######main######
#获取PATH变量的所有目录列表
folder=$(list_path)

#遍历PATH变量的目录,并用函数递归查询
for path in $folder
do
    echo $path
    listf "$path" "  "
done

在这里插入图片描述

例题演练三:
(3)将一个点分十进制格式的IP地址转换成点分二进制格式,比如 255.255.255.255 --> 11111111.11111111.11111111.11111111;

在这里插入图片描述

[root@clr /opt/mywork]# vim 7.sh

#将一个点分十进制格式的IP地址转换成点分二进制格式
#比如 255.255.255.255   -->  11111111.11111111.11111111.11111111

#定义一个用于十进制转换为二进制的函数
switch_bin() {
    NUM=$1
    for i in {1..8}
    do
        SUM=$[NUM % 2]$SUM
        let NUM/=2
    done
    echo $SUM
}

#定义一个用于分割IP的函数
SPT() {
    IP=$1
    for i in {1..4}
    do
        num=${IP%%.*}       
        IP=${IP#*.}      
        BIN=$(switch_bin num)  
        echo -n $BIN.
    done

}


#####main#####
read -p "请输入一个合法IP:" INIP
res=$(SPT $INIP)
echo ${res%.*}

4. 函数库文件

可以将经常使用的函数存入一个单独的函数文件,然后将函数文件载入shell,再进行调用函数.

实现函数文件的过程:

  • 创建函数文件,只存放函数的定义

  • 在shell脚本或交互式shell中调用函数文件,格式如下:

. ./filename
source filename

在脚本中加载函数库文件;

在这里插入图片描述
函数库文件:

[root@clr /opt/mywork]# vim clr.sh

#!/bin/bash

#函数库文件
jiafa() {
  echo $[$1 + $2]
}

jianfa() {
  echo $[$1 - $2]
}

chengfa() {
  echo $[$1 * $2]
}

chufa() {
  if [ $2 -eq 0 ];then
    echo "除数不可为0"
  else
    echo $[$1 / $2]
  fi
}

fact() {
  if [ $1 -eq 1 ];then
    echo 1
  elif [ $1 -gt 1 ];then
    local tmp=$[$1 - 1]
    local res=$(fact $tmp)  #在函数内调用函数
    echo $[$1 * res]
  else
    echo "输入的值无效。请输入大于等于1的整数!"
  fi
}                                                             

在脚本中加载函数库文件:

[root@clr /opt/mywork]# vim 8.sh

#!/bin/bash

#加载函数库文件到当前脚本的shell
source /opt/mywork/clr.sh

value1=10
value2=5

res1=$(jiafa $value1 $value2)
res2=$(jianfa $value1 $value2)
res3=$(chengfa $value1 $value2)
res4=$(chufa $value1 $value2)
res5=$(fact $value1 $value2)

echo "加法的结果为$res1"
echo "减法的结果为$res2"
echo "乘法的结果为$res3"
echo "除法的结果为$res4"
echo "阶乘的结果为$res5"

5.总结

函数

定义函数

(1)function 函数名 {代码块}
(2)函数名 () {代码块}

返回函数的值

(1)在函数内用return退出函数并返回函数的值,在函数外用echo $?获取返回值
注意:返回值的范围只能在0~255,超过部分需除以256取余

(2)在函数内用echo输出值,在函数体外可用 变量=$(函数名) 获取函数的返回值

如何给函数传参

在这里插入图片描述

函数变量的作用范围

函数默认只能在脚本内的shell环境有效(使用source执行脚本,也公影响系统当前的shell环境)

脚本中的变量默认全局有效(即函数体内外都有效)

在函数体内执执行local 变量,可将变量限定在函数体内部使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌上花开,静待绽放!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值