当前位置: 首页 > news >正文

[Shell编程] Shell 函数

如果你经常编写 Shell 脚本,会发现很多代码片段需要重复使用:比如计算某个值、检查文件状态、或者收集系统信息。如果每次都复制粘贴,不仅麻烦,还会让脚本臃肿难懂。这时候,Shell 函数就能帮你解决这些问题。

一、什么是 Shell 函数?为什么要用它?

简单来说,Shell 函数就是一组预先定义好的 Shell 命令集合,可以像 "工具" 一样被反复调用。它的优势主要有三点:

  • 速度快:函数定义后会被加载到内存,调用时无需从硬盘读取,比重复写命令效率更高;
  • 代码整洁:把独立功能封装成函数,让脚本结构更清晰,可读性更强;
  • 避免重复:一次定义,多次调用,再也不用复制粘贴相同代码,减少出错概率。

二、Shell 函数的定义:两种方式任你选

定义 Shell 函数很简单,有两种常用语法,初学者可以任选其一:

方式 1:使用function关键字

bash

function 函数名() {命令序列  # 函数要执行的操作[return 数值;]  # 可选,用于返回退出值
}

方式 2:省略function关键字(更简洁)

bash

函数名() {命令序列[return 数值;]
}
注意要点:
  • { 和 } 是函数体的边界,{ 可以和函数名同行,也可以单独占一行(但必须在句首);
  • return 语句用于退出函数并返回一个整数(0-255),0 表示成功,非 0 表示失败;
  • 若省略return,函数会默认以最后一条命令的执行结果作为返回值;
  • return vs exitreturn只退出当前函数,脚本继续执行;exit直接终止整个脚本。

三、函数的调用与返回值:如何使用定义好的函数?

定义好函数后,调用方法非常简单:直接写函数名,如果需要传参数,后面跟参数即可。

1️⃣基本调用示例

bash

# 定义一个简单函数
demoFun() {echo "这是我的第一个Shell函数!"
}# 调用函数(直接写函数名)
demoFun

执行脚本后,会输出:这是我的第一个Shell函数!

2️⃣返回值的获取:用$?查看结果

函数的返回值需要用$?变量获取,它会保存上一次命令(或函数)的退出状态。

bash

# 定义带返回值的函数
addNum() {echo "计算两个数字的和..."read -p "请输入第一个数字:" aread -p "请输入第二个数字:" breturn $((a + b))  # 返回两数之和(注意:返回值需在0-255之间)
}# 调用函数
addNum
echo "两数之和为:$?"  # 用$?获取返回值
注意:
  • 若两数之和超过 255(比如 256),$?会返回0(因为 256÷256=1 余 0),这是 Shell 的限制;
  • 若需要返回超过 255 的结果,建议直接在函数中用echo输出,再通过$(函数名)捕获(见下文实战案例)。

3️⃣必须先定义,后调用!

Shell 脚本是顺序执行的,函数必须在调用前定义,否则会报错。比如下面的代码会失败:

bash

# 错误示例:先调用,后定义
demoFun  # 此时函数还未定义,会报错
demoFun() {echo "Hello"
}

四、函数参数:给函数传递 "原材料"

和脚本一样,函数也可以接收参数,让功能更灵活。参数的使用规则如下:

  • 调用时:函数名 参数1 参数2 ...(函数名和参数用空格分隔);
  • 函数内部:用$1表示第一个参数,$2表示第二个,以此类推;
  • 第 10 个及以上参数:必须用${10}${11},否则$10会被解析为$1+0

常用的参数处理特殊变量

变量含义
$#参数的总个数
$*所有参数合并为一个字符串
$@所有参数,每个参数单独作为字符串(加引号时生效)
$?上一条命令的退出状态(0 表示成功)

实例:处理多个参数

bash

# 定义处理参数的函数
showParams() {echo "第一个参数:$1"echo "第二个参数:$2"echo "第十个参数:${10}"  # 注意用${10}echo "参数总数:$#"echo "所有参数:$*"
}# 调用函数,传递11个参数
showParams 1 2 3 4 5 6 7 8 9 10 11

执行结果:

plaintext

第一个参数:1
第二个参数:2
第十个参数:10
参数总数:11
所有参数:1 2 3 4 5 6 7 8 9 10 11

五、变量作用范围:全局变量与局部变量

在 Shell 函数中,变量的作用范围需要特别注意:

  • 默认全局有效:函数内部定义的变量,在函数外部也能访问;
  • 局部变量:用local关键字定义,仅在函数内部有效,不影响外部变量。

实例:全局变量 vs 局部变量

bash

# 全局变量示例
globalDemo() {a=100  # 未用local,全局有效
}
globalDemo
echo "全局变量a:$a"  # 输出100# 局部变量示例
localDemo() {local b=200  # 用local,局部有效echo "函数内的b:$b"  # 输出200
}
localDemo
echo "函数外的b:$b"  # 输出空(外部无法访问)

建议:在函数内部定义临时变量时,尽量用local,避免意外修改全局变量。

六、函数递归:自己调用自己的技巧

递归是指函数调用自身的行为,常用于处理有层次结构的问题(如目录遍历、阶乘计算)。

实例 1:计算阶乘(n! = n × (n-1) × ... × 1)

bash

fact() {if [ $1 -eq 1 ]; then  # 递归终止条件:1的阶乘是1echo 1elselocal temp=$(( $1 - 1 ))  # 计算n-1local res=$(fact $temp)  # 递归调用自身,计算(n-1)!echo $(( $1 * res ))  # n! = n × (n-1)!fi
}read -p "请输入一个数字:" n
echo "$n的阶乘是:$(fact $n)"

实例 2:递归遍历目录下的所有文件

bash

listFiles() {for f in $(ls $1); do  # 遍历$1目录下的内容if [ -d "$1/$f" ]; then  # 若为目录echo "$f:目录"listFiles "$1/$f"  # 递归遍历子目录else  # 若为文件echo "$f:文件"fidone
}# 遍历/root/a目录
listFiles "/root/a"

七、函数库:让函数复用更简单

如果多个脚本需要用到相同的函数,可以把函数集中放在一个 "函数库" 脚本中,其他脚本直接调用,无需重复定义。

步骤 1:创建函数库(如func_lib.sh

bash

# 定义加法函数
add() {echo $(( $1 + $2 ))
}# 定义减法函数
sub() {echo $(( $1 - $2 ))
}

步骤 2:在其他脚本中调用函数库

bash

# 引入函数库(注意路径)
source ./func_lib.sh  # 或 . ./func_lib.sh# 调用函数库中的函数
read -p "输入第一个数:" x
read -p "输入第二个数:" yecho "和:$(add $x $y)"
echo "差:$(sub $x $y)"

八、实战:定时生成系统性能报告

学会了 Shell 函数,我们来做一个实用工具:每小时采集一次 CPU、内存、磁盘使用情况,生成报告保存到文件中。

bash

#!/bin/bash# 定义输出目录(不存在则创建)
output_dir="/var/log/system_reports"
mkdir -p $output_dir# 1. 获取CPU使用率
get_cpu() {echo "===== CPU使用情况($(date)) ====="top -bn1 | grep "Cpu(s)"  # top命令获取CPU信息echo
}# 2. 获取内存使用率
get_mem() {echo "===== 内存使用情况 ====="free -h  # 简化显示内存信息echo
}# 3. 获取磁盘使用率
get_disk() {echo "===== 磁盘使用情况 ====="df -h  # 简化显示磁盘信息echo
}# 4. 生成报告
generate_report() {# 报告文件名:包含日期(如report-20240809.txt)report_file="$output_dir/report-$(date +%Y%m%d).txt"# 写入报告内容get_cpu >> $report_fileget_mem >> $report_fileget_disk >> $report_fileecho "报告已生成:$report_file"
}# 主循环:每小时生成一次报告
while true; dogenerate_reportsleep 3600  # 暂停3600秒(1小时)
done

使用方法:

  1. 保存为sys_report.sh,添加执行权限:chmod +x sys_report.sh
  2. 后台运行:./sys_report.sh &
  3. 查看报告:cat /var/log/system_reports/report-20240809.txt

九、总结:Shell 函数学习要点

  1. 核心价值:组织代码、提高复用性、加快执行速度;
  2. 基础语法:两种定义方式,注意returnexit的区别;
  3. 参数处理:用$1$2... 传参,$#$*等处理参数集合;
  4. 变量作用域:local关键字定义局部变量,避免全局污染;
  5. 进阶技巧:递归解决层次问题,函数库实现代码复用;
  6. 实战关键:结合实际需求封装功能,比如系统监控、日志分析等。
http://www.dtcms.com/a/323582.html

相关文章:

  • PyQt5技术栈简述
  • .htaccess 文件上传漏洞绕过总结
  • Linux文件操作详解:一切皆文件
  • 编辑距离-二维动态规划
  • SkyWalking-3--Java Agent开发和集成示例
  • AI智能编程工具汇总
  • ComfyUI版本更新---解决ComfyUI的节点不兼容问题
  • MySQL 主备(Master-Slave)复制 的搭建
  • SOLIDWORKS 2025对工具栏等进行了重新布局和优化
  • GoEnhance AI-AI视频风格转换工具
  • gRPC 全面解析与实战 —— 从原理到同步/异步开发全攻略
  • Linux系统编程——进程地址空间
  • GM3568JHF:FPGA+ARM异构开发板环境搭建教程
  • 嵌入式学习day23-shell命令
  • Qdrant Filtering:must / should / must_not 全解析(含 Python 实操)
  • 【Python 高频 API 速学 ②】
  • 【线程池】压测确定线程池合适的参数
  • 【js】判断异步函数的返回值要加await
  • 使用LangGraph从零构建多智能体AI系统:实现智能协作的完整指南
  • 计算机系统设计中都有什么任务~计算密集~IO密集~逻辑密集等
  • 提示条贴合右侧边栏
  • java web项目入门了解
  • 天地图,cesium,leaflet
  • java练习题:数字位数
  • Windows下使用PyInstaller打包PyQt项目
  • 第15届蓝桥杯Scratch图形化省赛中级组2024年8月24日真题
  • 4深度学习Pytorch-神经网络--损失函数(sigmoid、Tanh、ReLU、LReLu、softmax)
  • Linux-JSON Schema
  • Java类和对象课上练习题目设计
  • LLM 的向量的方向表示语义,向量长度表示什么