Linux函数

目录

一、脚本函数

1.1 创建函数

1.2 使用函数

二、函数返回值

2.1 默认的退出状态码

2.2 使用return命令

 2.3 使用函数输出

三、在函数中使用变量

3.1 向函数传达参数

3.2 在函数中处理变量

四、数组变量和函数

4.1 向函数中传递数组

 4.2 从函数中返回数组

五、函数递归


一、脚本函数

1.1 创建函数

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

function name {commands
}

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

第二种创建函数的方法:

name() {commands
}

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

1.2 使用函数

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

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

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

二、函数返回值

2.1 默认的退出状态码

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

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bashfunc1() {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 ,因为函数中的最后一条命令执行失败了。但是你无法知道该函数中其他命令是否执行成功。看下面例子:

 

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bashfunc1() {ls notexist_fileecho "该条命令正常执行,退出状态码是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,如下所示:

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

 2.3 使用函数输出

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

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bashfunc1() {read -p "请输入一个整数:" valueecho $[ $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 向函数传达参数

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

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bashfunc1() {if [ $# -eq 0 ] || [ $# -gt 2 ]thenecho -1elif [ $# -eq 1 ]thenecho $[ $1 + $1 ]elseecho $[ $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 ~]#

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

 

[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/bashfunc1() {echo $[ $1 + $2 ]
}
echo $(func1 $1 $2)[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash function.sh  12 42
54
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

3.2 在函数中处理变量

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

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

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

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

四、数组变量和函数

4.1 向函数中传递数组

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

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

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

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bashfunc1() {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 从函数中返回数组

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bashfunc1() {local org_arry=(`echo "$@"`)local ielements=$[ $# - 1 ]for (( i=0;i<=$elements;i++ ))dolocal new_arry[$i]=$[ ${org_arry[$i]} * 2 ]doneecho "新数组是:${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 ~]#

五、函数递归

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

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat function.sh
#! /bin/bashfunc1() {if [ $1 -eq 1 ]thenecho 1elselocal 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 ~]#

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/835720.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【1】STM32·FreeRTOS·新建工程模板【一步到位】

目录 一、获取FreeRTOS源码 二、FreeRTOS源码简介 2.1、FreeRTOS源码文件内容 2.2、FreeRTOS内核 2.3、Source文件夹 2.4、portable文件夹 三、FreeRTOS手把手移植 3.1、FreeRTOS移植准备 3.2、FreeRTOS移植步骤 3.2.1、将 FreeRTOS 源码添加至基础工程、头文件路径等…

基于Matplotlib的模型性能可视化工作

一、项目简介 本项目是科技考古墓葬识别工作的中间过程&#xff0c;因为需要大量复用所以另起一章好了。 主要涉及到数据读取、数据可视化和少量的数据处理过程。 二、相关知识 PandasMatplotlib 三、实验过程 1. 数据探索性分析 1.1 准备工作–导入模块 import pandas…

用python写个控制MicroSIP自动拨号和定时呼叫功能(可用在小型酒店叫醒服务)MicroSIP定时拨号

首先直接上结果吧&#xff0c;MicroSIP 助手&#xff0c;控制MicroSIP自动拨号&#xff0c;定时呼叫的非常实用小工具&#xff01; 在使用MicroSIP 助手之前&#xff0c;我们需要了解MicroSIP是什么&#xff0c;MicroSIP是一个SIP拨号软件&#xff0c;支持注册任意SIP平台实现拨…

【xxl-job | 第三篇】SpringBoot整合xxl-job

文章目录 3.SpringBoot整合xxl-job3.1定时任务服务配置3.1.1导入maven依赖3.1.2yml配置3.1.3XxlJobConfig配置类3.1.4定时任务类 3.2xxl-job配置3.2.1新增执行器3.2.2新增任务3.2.3执行任务3.2.4查看日志3.2.5查看任务后台日志 3.3小结 3.SpringBoot整合xxl-job 3.1定时任务服…

AppBuilder低代码体验:构建雅思大作文组件

AppBuilder低代码体验&#xff1a;构建雅思大作文组件 ​ 在4月14日&#xff0c;AppBuilder赢来了一次大更新&#xff0c;具体更新内容见&#xff1a;AppBuilder 2024.04.14发版上线公告 。本次更新最大的亮点就是**新增了工作流&#xff0c;低代码制作组件。**具体包括&#x…

区块链链底层架构,IPFS,DAPP

目录 区块链链底层架构 IPFS,DAPP等去中心化应用实现机制和运行原理 DApp到底在哪运行,举例说明

Python梯度下降算法

梯度下降&#xff08;Gradient Descent&#xff09;是机器学习中用于最小化损失函数的优化算法。在Python中&#xff0c;可以通过手动实现或使用现有的库&#xff08;如scikit-learn&#xff09;来应用梯度下降算法。以下是手动实现简单线性回归问题的梯度下降算法的示例&#…

聚合工程搭建、工程依赖导入

上一章讲了自动化云测平台的一些环境的准备 如果还未完成云服务器的环境搭建和本地环境的搭建&#xff0c;请点击左侧 -> 传送门 那么正式开始这一章的内容 聚合工程搭建 创建项目 我们先给项目命个名&#xff1a;xxx-meter&#xff0c;构建系统&#xff0c;我们选择M…

前端开发指导

前端开发指导 本文介绍了配置前端开发环境需要的软件、配置项等,指导如何开始进行UDM部门前端开发的全流程。本文以Windows系统下在Microsoft Virtual Studio Code中开发为基础。 一、综述 目标:零基础或者新员工依照此文档,能够完成开发环境的搭建及熟悉测试环境的搭建。…

VBScript字符串赋值注意事项

VBScript中字符串是用双引号来包裹。 单引号在VBScript里是注释符&#xff0c;不过如果要放在字符串里的话&#xff0c;直接写在双引号的字符串里就可以&#xff0c;跟其他字符比起来&#xff0c;并不特殊。 双引号如果要放在字符串里&#xff0c;则需要处理一下&#xff0c;可…

代码审计平台sonarqube的安装及使用

docker搭建代码审计平台sonarqube 一、代码审计关注的质量指标二、静态分析技术分类三、使用sonarqube的目的四、sonarqube流程五、docker快速搭建sonarqube六、sonarqube scanner的安装和使用七、sonarqube对maven项目进行分析八、sonarqube分析报告解析九、代码扫描规则定制十…

【Python 常用脚本及命令系列 1.2 -- python 判断串口是否已经打开】

请阅读【嵌入式开发学习必备专栏】 文章目录 判断串口是否打开 判断串口是否打开 要在Python中打印串口的波特率并检查特定的串口&#xff08;例如COM19&#xff09;是否已经打开&#xff0c;你可以使用pyserial库。这个库提供了跨平台的串口通信功能。首先&#xff0c;确保安…

python之异常机制处理

1.异常机制 1_1 try和except&#xff1a; 异常&#xff1a;程序无法继续执行了&#xff0c;例如&#xff1a;字符串和数字相加&#xff0c;除以0&#xff0c;对None进行操作 中断当前程序执行&#xff0c;然后打印出红字 Exception error 捕捉异常的方式&#xff1a;关键…

【数据分析】 JupyterNotebook安装及使用简介

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 在数据分析中&#xff0c;一般用Pycharm编辑代…

codeforces round 149 div2(a,b,c,d)

手速场&#xff0c;可惜我傻逼卡 c c c了 题目链接 A #include<bits/stdc.h>using namespace std;#define int long long #define PII pair<int,int>void solve() {int n,k;cin>>n>>k;if(n<k){cout<<1<<\n;cout<<n<<\n;}…

VSCode:设置顶部文件标签页滚动条的宽度

使用VSCode打开多个文件后&#xff0c;顶部的文件标签可以通过滚动条进行滚动&#xff0c;但是缺点是该滚动条太窄了&#xff0c;不好选择。 可以通过如下方法修改改滚动条的宽度&#xff1a; 1.点击设置 2.选择工作台->编辑管理->Title Scrollbar Sizing->Large 3.可…

书生浦语训练营第四次课作业

基础作业 环境配置 拷贝internlm开发机内的环境 studio-conda xtuner0.1.17# 激活环境 conda activate xtuner0.1.17 # 进入家目录 &#xff08;~的意思是 “当前用户的home路径”&#xff09; cd ~ # 创建版本文件夹并进入&#xff0c;以跟随本教程 mkdir -p /root/xtuner0…

无需关注---使用docker-compose部署你的springboot框架的java项目

version: ‘3’ services: springboot: image: openjdk:11-jre-slim ports: - “20221:20221” volumes: - ./2022.jar:/app/2022.jar working_dir: /app command: [“java”, “-Xmx256m”, “-Xms128m”, “-jar”, “2022.jar”] # 调整堆内存大小 restart: always environm…

专项技能训练五《云计算网络技术与应用》实训8-1:建立基于OpenvSwitch的GRE隧道

文章目录 建立基于OpenvSwitch的GRE隧道1. 使用VMware安装2个CentOS 7虚拟机&#xff0c;安装时记得都开启CPU虚拟化&#xff0c;第一台命名为“Docker”&#xff0c;第二台命名为“KVM”。2. 安装完虚拟机后&#xff0c;进入虚拟机&#xff0c;修改网络配置&#xff08;onboot…

进程间通信(二)

共享内存 当进程A和进程B有一块共享的内存空间时&#xff0c;这两个进程之间的数据交互就会变的很简单&#xff0c;只需要像读取自己内存空间中的元素一样去读取数据即可。实现共享内存进行数据交互的一般步骤&#xff1a; 创建/打开共享内存内存映射数据交换断开与共享内存的…