【LinuxShell】Shell编程之函数

文章目录

  • 一.函数
  • 二.定义函数
  • 三.返回函数的值
  • 四.函数的传参
  • 五.函数变量的作用范围
  • 六.函数的递归
  • 七.函数库


一.函数

  Shell 函数的本质是一段可以重复使用的脚本代码,这段代码被提前编写好了,放在了指定的位置,使用时直接调取即可。使用Shell函数可以将大的工程分割为若干小的功能模块,代码的可读性更强。

二.定义函数

  函数定义的格式有两种,一种是使用function定义的,另一种是函数名定义的。具体定义方式如下:

方式一

function name{
  	命令序列
}

方式二

name(){
  	命令序列
}

其中对各个部分的说明:

  • function是 Shell 中的关键字,专门用来定义函数;
  • name是函数名;
  • { }包围的部分称为函数体,调用一个函数,实际上就是执行函数体中的代码。

三.返回函数的值

  函数返回值的方式有两种,分别是returnecho

使用return返回值:

​   使用return返回值,只能返回0-255的整数,超出的值将会除以256取余。

​   函数使用return返回值,通常以用$?变量显示该值,因此通常仅返回0或1;0表示成功,1表示失败。

例如:

function db1 {
	read -p "请输入:" value
	return $[$value *2]
}
db1
echo $?

使用echo返回值:

​   使用echo可以返回任何字符串结果。

​   通常用于返回数据,比如一个字符串值或者列表值。好处就是可以再次利用echo来对输出的值做二次操作

例如:

db1(){
	read -p "请输入" value
	echo $[$value * 2]
}
result=`db1`
echo $result

四.函数的传参

函数体内部

  1. ​ 函数体内部的$1 $2代表的是调用函数时,函数后面跟的位置参数
  2. ​ 在函数体内部的$#代表调用函数时,函数后面跟的参数个数
  3. ​ 在函数内部的$@ $*代表调用函数时,函数后面跟的所有参数

函数体外部

  1. ​ 函数体外的$1 $2 代表的是执行脚本时,脚本后面跟的位置参数
  2. ​ 在函数体外时,$#代表脚本后面跟的参数个数
  3. ​ 在函数体外时,$@ $*代表脚本后面跟的所有参数

其中不管在函数体内还是在函数体外,$0都代表脚本本身。

例子1:基本用法

[root@localhost ~]# vim demo1.sh
#!/bin/bash
sum2(){
	#函数体内部的$1 $2代表的是调用函数时,函数后面跟的位置参数
	sum=$[$1 - $2]
	echo $sum
}
#函数体外的$1 $2代表的是执行脚本时,脚本后面跟的位置参数
sum2 $2 $1

[root@localhost ~]# bash demo1.sh 10 20
30

例子2:其他用法

[root@localhost ~]# vim demo2.sh
#!/bin/bash
#定义函数
sum2(){
	#函数体内部的$1 $2代表的是调用函数时,函数后面跟的位置参数
	sum=$[$1 - $2]
	echo $sum
	echo "在函数体内部的\$#代表调用函数时,函数后面跟的参数个数,当前函数后面有$#个参数"
	echo "在函数体内部的\$Q@代表调用函数时,函数后面跟的所有参数,当前函数后面的参数有:$@"
	echo "在函数体内部,\$0代表$0"
}
#调用函数
echo "在函数体外时,\$#代表脚本后面跟的参数个数,当前脚本后面有$#个参数"
echo "在函数体外时,\$@代表脚本后面跟的所有参数,当前脚本后面参数有:$@"
echo "在函数体外,\$0代表$0"
#函数体外的$1 $2代表的是执行脚本时,脚本后面跟的位置参数
sum2 $2 $1

[root@localhost ~]# bash demo2.sh  10 20
在函数体外时,$# 代表脚本后面跟的参数个数,当前脚本后面有 2 个参数
在函数体外时,$@代表脚本后面跟的所有参数,当前脚本后面参数有:10 20
在函数体外,$0代表demo2.sh
demo2.sh:行4: cho: 未找到命令
在函数体内部的$#代表调用函数时,函数后面跟的参数个数,当前函数后面有2个参数
在函数体内部的$Q@代表调用函数时,函数后面跟的所有参数,当前函数后面的参数有:20 10
在函数体内部,$0代表demo2.sh

五.函数变量的作用范围

  1. 函数在Shell脚本中仅在当前脚本Shell环境中有效(使用source或者. 执行脚本,也会影响系统的当前Shell环境)
  2. Shell脚本中变量默认全局有效
  3. 将变量限定在函数内部使用local命令
  4. 系统Shell环境>>脚本Shell环境>>函数Shell环境

例子1:外面定义的i被函数里面的定义i所覆盖,所以输出函数里面的数字

[root@localhost ~]# vim demo3.sh
#!/bin/bash
list(){
  i=7
  echo $i
}
i=4
list
echo $i

[root@localhost ~]# bash demo3.sh 
7
7

例子2:函数里面的i被定义成了局部变量在函数外不生效

[root@localhost ~]# vim demo4.sh
 #!/bin/bash
list(){
  local i=9
  echo $i
}
i=8
list
echo $i

[root@localhost ~]# bash demo4.sh 
9
8

六.函数的递归

  递归就是一个函数在它的函数体内调用它自身。执行递归函数将反复调用其自身,每调用一次就进入新的一层。所以递归要有两个基本要素,结束条件与递推关系。

  递归的两个基本要素
    1.边界条件:确定递归到何时结束,也被称为递归的出口
    2.递归所使用的模式:大问题分解成小问题。递归函数只有具有上述两个条件,才能计算出结果。

例子1:使用递归计算阶乘

[root@localhost ~]# bash demo5.sh
#!/bin/bash    
fact() {
	#$1表示调用函数时,后面跟的位置参数。如果值是1,就输出1。      
    if [ $1 -eq 1 ]      
    then          
        echo 1      
    else  
	#定义一个本地变量temp,变量值为每次传入的参数值减1          
    local temp=$[$1 - 1]  
	#不停地调用函数自身,直到temp的值等于1          
    local result=$(fact $temp)          
    echo $[$1 * $result]      
fi  
} 
########## main ###########  
read -p "请输入一个正整数:" num
a=$(fact $num)  
echo "$num 的阶乘为:$a"

[root@localhost ~]# bash demo5.sh
请输入一个正整数:5 
5 的阶乘为:120

例子2:使用递归查询目录

[root@localhost ~]# vim demo6.sh 
function list_files {
for f in `ls $1`
do
	#判断opt目录下的各个子目录以及文件  
	if [ -d "$1/$f" ]
	then
		#opt目录下的目录首行缩进,如果是查询第一次就不缩进,如果不是第一次查询就调用之前的$2的进行首行缩进
		echo "$2/$f"
		#递归查询opt目录下子目录下的文件和目录,并且将$2空两个字符进行缩进
		list_files "$1/$f" " $2"
	else
		#如果是文件直接输出
		echo "$2$f"
	fi
done
}
list_files "/opt" ""

[root@localhost ~]# bash demo6.sh 
/data
  /aa
    /bb
      /cc
        /dd
          abcd.txt
/rh

七.函数库

  我们可以事先创建一个函数库文件,在里面定义各种常用的函数,然后可以在别的shell脚本中直接引用这个函数库文件,使得不需要在新的shell脚本中再次定义函数而是可以直接调用此函数。

注意:

1.source.是在当前shell环境中运行脚本。

2.如果函数库文件中定义了变量的话,切换bash环境就不生效了。所以在脚本中引用函数库文件的时候,一定要使用source或者.

3.引用函数库文件时候 ,建议使用绝对路径,避免文件丢失。

创建一个函数库文件

[root@localhost ~]# vim funcs.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
}

在其他的shell脚本中执行函数

[root@localhost ~]# vim demo7.sh 
#!/bin/bash
#加载函数库文件到当前脚本的shell
. /root/funcs.sh

read -p "请输入第一个正整数:" value1  
read -p "请输入第二个正整数:" value2

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"

[root@localhost ~]# bash demo7.sh
请输入第一个正整数:10
请输入第二个正整数:5
加法的结果为15
减法的结果为5
乘法的结果为50
除法的结果为2
阶乘的结果为3628800

你可能感兴趣的:(Shell基础,网络,linux)