Linux函数

目录

一、脚本函数

[1.1 创建函数](#1.1 创建函数)

[1.2 使用函数](#1.2 使用函数)

二、函数返回值

[2.1 默认的退出状态码](#2.1 默认的退出状态码)

[2.2 使用return命令](#2.2 使用return命令)

[2.3 使用函数输出](#2.3 使用函数输出)

三、在函数中使用变量

[3.1 向函数传达参数](#3.1 向函数传达参数)

[3.2 在函数中处理变量](#3.2 在函数中处理变量)

四、数组变量和函数

[4.1 向函数中传递数组](#4.1 向函数中传递数组)

[4.2 从函数中返回数组](#4.2 从函数中返回数组)

五、函数递归


一、脚本函数

1.1 创建函数

在bash shell脚本中创建函数的语法有两种。第一种是使用关键字function,随后跟上分配给该代码块的函数名:

bash 复制代码
function name {
    commands
}

name 定义了该函数的唯一名称。脚本中函数名不能重复。

第二种创建函数的方法:

bash 复制代码
name() {
    commands
}

函数名后的空括号表明正在定义的是一个函数。

1.2 使用函数

要在脚本中使用函数,只需写出函数名即可。

函数定义不一定非要放在shell脚本的最开始部分,但是要在调用函数之前定义函数。

如果定义了同名函数,那么新定义的就会覆盖函数原先的定义,而这一切不会有任何错误信息。

二、函数返回值

2.1 默认的退出状态码

在默认情况下,函数的退出状态码是函数中最后一个命令返回的退出状态码。函数执行结束后,可以使用标准变量 $? 来确认函数的退出状态码

bash 复制代码
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bash

func1() {
  echo "该条命令正常执行,退出状态码是0"
  ls notexist_file
}
echo "测试函数"
func1
echo "函数退出状态码是:$?"
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh
测试函数
该条命令正常执行,退出状态码是0
ls: cannot access notexist_file: No such file or directory
函数退出状态码是:2
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

该函数的退出状态码是 2 ,因为函数中的最后一条命令执行失败了。但是你无法知道该函数中其他命令是否执行成功。看下面例子:

bash 复制代码
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bash

func1() {
  ls notexist_file
  echo "该条命令正常执行,退出状态码是0"
}
echo "测试函数"
func1
echo "函数退出状态码是:$?"
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh
测试函数
ls: cannot access notexist_file: No such file or directory
该条命令正常执行,退出状态码是0
函数退出状态码是:0
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

这次由于函数中最后一条命令执行成功,所以函数的退出状态码是 0 ,不过其中的其他命令执行失败。使用函数默认退出状态码是一种危险的行为。

2.2 使用return命令

bash shell会使用return命令以特定的状态码退出函数。return 命令允许指定一个整数值作为函数的退出状态码。但是用这种方法返回退出状态码一定注意两个问题:1)函数执行一结束就立刻读取返回值;2)退出状态码必须介于0-255,如下所示:

bash 复制代码
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bash

func1() {
  read -p "请输入一个整数:" value
  return $[ $value * 2 ]
}
func1
echo "函数退出状态码是:$?"
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh
请输入一个整数:4
函数退出状态码是:8
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh
请输入一个整数:200
函数退出状态码是:144
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

2.3 使用函数输出

正如可以将命令的输出保存到 shell 变量中一样,也可以将函数的输出保存到 shell 变量中,如下:

bash 复制代码
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bash

func1() {
  read -p "请输入一个整数:" value
  echo $[ $value * 2 ]
}
result=$(func1)
echo "函数退出状态码是:$result"
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh
请输入一个整数:255
函数退出状态码是:510
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

注意函数中 echo $[ $value * 2 ],而非return $[ $value * 2 ]

这个例子演示了一个不易察觉的技巧。注意,函数func1实际上输出了两条信息,read 命令输出了一条简短的提示消息。bash shell 非常聪明,并不将其作为STDOUT输出的一部分,而是直接将其忽略。如果用 echo 语句生成这条消息来询问用户,那么他就会与输出值一起被读入shell 变量。

注意 这种方法还可以返回浮点值和字符串,这使其成为一种获取函数返回值的强大方法。

三、在函数中使用变量

3.1 向函数传达参数

注意 在脚本中调用函数时,必须将参数和函数名放在同一行。

bash 复制代码
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bash

func1() {
  if [ $# -eq 0 ] || [ $# -gt 2 ]
  then
     echo -1
  elif [ $# -eq 1 ]
  then
     echo $[ $1 + $1 ]
  else
     echo $[ $1 + $2 ]
  fi
}
echo -n "传入2个参数:"
value=$(func1 10 11)
echo $value
echo -n "传入1个参数:"
value=$(func1 10)
echo $value
echo -n "传入3个参数:"
value=$(func1 10 11 12)
echo $value
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh
传入2个参数:21
传入1个参数:20
传入3个参数:-1
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

要在函数中使用脚本的命令行参数,必须在调用函数时将其手动传入

bash 复制代码
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh 1 2
function.sh: line 4: +  : syntax error: operand expected (error token is "+  ")

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

# 手动传入脚本的命令行参数

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bash

func1() {
  echo $[ $1 + $2 ]
}
echo $(func1 $1 $2)

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh  12 42
54
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

3.2 在函数中处理变量

无须在函数中使用全局变量,任何在函数内部使用的变量都可以被声明为局部变量。为此,只需在变量声明之前加上 local 关键字,如下示例:

bash 复制代码
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bash

func1() {
  temp=$[ $value + 6 ]
  result=$[ $temp * 2 ]
}
temp=4
value=6
func1
echo "The result is $result"
if [ $temp -gt $value ]
then
   echo "temp is larger"
else
   echo "temp is smaller"
fi
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh
The result is 24
temp is larger
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

输出的结果是temp大于values,就是因为函数中使用了temp变量,因此它的值在脚本中受到了影响,产生了意想不到的结果。一种解决的办法是函数中使用局部变量,如下示例:

bash 复制代码
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bash

func1() {
  local temp=$[ $value + 6 ]
  result=$[ $temp * 2 ]
}
temp=4
value=6
func1
echo "The result is $result"
if [ $temp -gt $value ]
then
   echo "temp is larger"
else
   echo "temp is smaller"
fi
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh
The result is 24
temp is smaller
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

四、数组变量和函数

4.1 向函数中传递数组

向脚本函数传递数组变量的方法有点难以理解。将数组变量当作单个参数传递的话,他不起作用。

bash 复制代码
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bash

func1() {
  echo "传递的参数是:$@"
  this_arry=$1
  echo "传入的数组是:${this_arry[*]}"

}
arry=(1 2 3 4)
echo "原始数组是:${arry[*]}"
func1 $arry
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh
原始数组是:1 2 3 4
传递的参数是:1
传入的数组是:1
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

可以看出,将数组变量作为函数参数进行传递,则函数只会提取数组变量的第一个元素。要解决这个问题,必须将数组变量拆解成多个数组元素,然后将这些数组元素作为函数参数传达。最后在函数内部,将所有的参数重组为一个新的数组变量。示例如下:

bash 复制代码
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bash

func1() {
  echo "传递的参数是:$@"
  local new_arry=(`echo "$@"`)
  echo "新数组是:${new_arry[*]}"
}
arry=(1 2 3 4)
echo "原始数组是:${arry[*]}"
func1 ${arry[*]}
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh
原始数组是:1 2 3 4
传递的参数是:1 2 3 4
新数组是:1 2 3 4
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

4.2 从函数中返回数组

bash 复制代码
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bash

func1() {
  local org_arry=(`echo "$@"`)
  local i
  elements=$[ $# - 1 ]
  for (( i=0;i<=$elements;i++ ))
  do
    local new_arry[$i]=$[ ${org_arry[$i]} * 2 ]
  done
  echo "新数组是:${new_arry[*]}"
}
arry=(1 2 3 4)
echo "原始数组是:${arry[*]}"
func1 ${arry[*]}
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh
原始数组是:1 2 3 4
新数组是:2 4 6 8
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

五、函数递归

局部函数变量的一个特性是自成体系。除了获取函数参数外,自成体系的函数不需要任何外部资源。这个特性使得函数可以递归调用,也就是说函数可以调用自己得来的结果。递归函数通常有一个最终可以迭代到的基准值。

bash 复制代码
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bash

func1() {
  if [ $1 -eq 1 ]
  then
    echo 1
  else
    local temp=$[ $1 -1 ]
    local result=$(func1 $temp)
    echo $[ $result * $1 ]
  fi
}
read -p "阶乘数:" value
result=$(func1 $value)
echo "$value阶乘的结果是:$result"
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh
阶乘数:6
6阶乘的结果是:720
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#
相关推荐
小陈phd31 分钟前
Vscode LinuxC++环境配置
linux·c++·vscode
是阿建吖!35 分钟前
【Linux】进程状态
linux·运维
明明跟你说过1 小时前
Linux中的【tcpdump】:深入介绍与实战使用
linux·运维·测试工具·tcpdump
Komorebi.py2 小时前
【Linux】-学习笔记05
linux·笔记·学习
Mr_Xuhhh2 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
内核程序员kevin5 小时前
TCP Listen 队列详解与优化指南
linux·网络·tcp/ip
朝九晚五ฺ10 小时前
【Linux探索学习】第十四弹——进程优先级:深入理解操作系统中的进程优先级
linux·运维·学习
自由的dream10 小时前
Linux的桌面
linux
xiaozhiwise10 小时前
Makefile 之 自动化变量
linux