Linux系统入门第十一章 --Shell编程之函数与数组

一、Shell函数

1、函数的用法

Shell函数可用于存放一系列的指令。在Shell脚本执行的过程中,函数被置于内存中,每次调用函数时不需要从硬盘读取,因此运行的速度比较快。在Shell编程中函数并非是必须的元素,但使用函数可以对程序进行更好的组织。将一些相对独立的代码变成函数,可以提高程序可读性与重用性,避免编写大量重复代码

格式:

function() {代码块
[return x]}function
function关键字表示定义一个函数,可以省略
{表示函数执行命令的入口,该符号可以与函数名同行也可以在函数名下一行的句首
}符号表示函数体结束,两个大括号之间{}是函数体
代码块可以是任意的 Shell 命令,也可以调用其他函数
return表示退出函数返回一个退出值,通过返回值判断执行是否成功,也可以使用 exit 终止整个 Shell 脚本

Shel1 函数调用的方法为:函数名「参数 1]〔参数 2]

栗子1:两个数求和

#!/bin/bash
#定义 sum 函数
sum() {
read -p "请输入第一个数字:" A
#检查是否为有效数字
if ! [[ $A =~ ^[0-9]+$  ]]
thenecho "这不是一个有效数字,请重新输入"return 1
firead -p "请输入第二个数字:" B
if ! [[ $B =~ ^[0-9]+$  ]]
thenecho "这不是一个有效数字,请重新输入"return 1
fi#计算两数之和
result=$((A + B))
echo "两数之和是:$result"
}
#调用函数
sum

执行结果:

栗子2:监控系统资源

该函数会定期监控系统的 CPU 和内存使用率,当使用率超过设定的值时,会发送报警信息,这里简单模拟为输出到控制台,实际应用中可扩展为发送邮件、短信等。

#!/bin/bash
send_alert() {local message=$1
echo "ALERT:$message"}#系统资源控制函数
monitor_system_resources() {local cpu_threshold=$1
local mem_threshold=$1
local interval=$3while true
do
#获取CPU的使用率
cpu_usage=$(top -bn1 | grep Cpu | awk '{print $2+$4}')
#获取内存使用率
mem_usage=$(free | grep Mem | awk '{print $3/$2 *100}')if (($(echo "$cpu_usage > $cpu_threshold" |bc -l)))
thensend_alert "CUP usage (${cpu_usage}%)"
fiif (($(echo "$mem_usage > $mem_threshold" |bc -l)))
thensend_alert "Mem usage (${mem_usage}%)"
fisleep "$interval"done
}
#调用函数
monitor_system_resources 2 5 2

执行结果:

参数说明:函数接收三个参数分别是CPU使用率值内存使用率值以及监控间隔时间(秒)

循环监控:使用 while true 循环不断监控系统资源。通过 top 和 free 命令获取 CPU 和内存使用率,使用 bc 命令进行浮点数比较。

报警处理:当使用率超过阈值时,调用 send alert 函数发送报警信息

2、函数变量的作用范围

在 Shel1 脚本中函数的执行并不会开启一个新的子 Shell,而是仅在当前定义的 shel1 环境中有效。如果 Shel1 脚本中的变量没有经过特殊设定,默认在整个脚本中都是有效的。
在编写脚本时,有时需要将变量的值限定在函数内部,可以通过内置命令 1ocal 来实现。函数内部变量的使用,可以避免函数内外同时出现同名变量对脚本结果的影响。local 命令的使用如下所示。

#!/bin/bash
AAA(){
local i 
i=8     
echo $i
}       
i=9
AAA
echo $i

上述脚本中,AAA 函数内部使用了 local 命令设置变量 i,其作用是将变量 i 限定在函数内部AAA 函数外部同样定义了变量 ,内部变量 i 和全局变量 i 互不影响。脚本执行时先调用了函数AAA,函数内部变量 i 为 8,所以输出结果是 8。调用完函数之后,给变量i 赋值为 9,再打印外部变量 i,所以又输出 9

3、递归函数

Shell 也可以实现递归函数,就是可以调用自己本身的函数。在 Linux 系统上编写shell脚本的时候,经常需要递归遍历系统的目录,列出目录下的文件和目录,逐层递归列出,并对这些层级关系进行展示。具体的实现过程如下所示

#!/bin/bash
#定义递归遍历目录的函数
traverse_directory() {
local dir=$1
#遍历当前目录下所有的目录和文件
for item in "$dir"/*
do      if [ -d "$item"  ]then    
#如果是目录则递归调用函数继续循环echo "这是目录:$item"traverse_directory "$item"elif [ -f "$item"  ]then    
#如果是文件就输出路径echo "这是文件:$item"fi      
done    
}
#调用函数
#“.”:当前目录
traverse_directory "."

执行结果:

二、Shell数组

在 shell 脚本中,数组是一种常见的数据结构,主要的应用场景包括:获取数组长度、获取元素长度、遍历元素、元素切片、元素替换、元素删除等等。shell中的数组与 Java、c、Python 不同,只有一维数组,没有二维数组。数组元素的大小与限制,也不需要事先定义。Shell 数组用括号()来表示,元素用空格分隔,元素的下标与大部分编程语言类似从开始。

fruits=("Apple" "Banana" "Cherry")  # 元素带空格时必须加引号
nums=(10 20 30)                    # 数字类型可不加引号

1、获取数组长度

在 shell 编程中,数组是一种用于存储多个值的数据结构。获取数组长度(即数组中元素的个数)在很多场景下都非常有用,比如进行数组遍历、数据处理等。普通数组是 Shell 中最常见的数组类型,其下标是从0 开始的连续整数。获取普通数组长度可以使用 ${#数组名[@]}或 ${#数组名[*]} 这两种语法,它们的效果是一样的。

#定义一个数组A
A=(1 2 3 4 5 6)#打印数组A的长度
#方法一:
echo ${#A[@]}
#方法二:
echo ${#A[*]}

2、读取指定元素对应的值

在 shell 编程里,你可以读取数组中指定下标的元素,也可以给指定下标的数组元素赋值。普通数组是 Shell 中最常用的数组类型,其下标是从0开始的整数

#定义一个数组A
A=(1 2 3 4 5 6)#读取3号元素对应的值
echo ${A[3]}#读取数组中所有的元素值
echo ${A[@]
echo ${A[*]

3、数组遍历

在 Shell 编程里,数组遍历指的是按顺序访问数组中的每一个元素,并对这些元素执行特定操作的过程,这在处理一组相关数据时非常有用,比如批量处理文件、统计数据等

#!/bin/bash
A=("好" "好" "学" "习" "天" "天" "向" "上")
for i in ${A[@]}
do      echo $i
done

执行结果:

4、数组切片

数组切片是一种操作,用于从数组中提取出一部分连续的元素,形成一个新的数组。这个操作在很多编程语言中都有支持,不过不同语言实现数组切片的语法和方式会有所差异。在Bash脚本里,也可以进行数组切片操作,语法是${array[@]:start:length},其中start是开始的索引,length是要提取的元素个数

#定义一个数组A
A=(1 2 3 4 5 6)echo ${A[@]}echo ${A[@]:0:5}echo ${A[@]:1:5}

5、数组替换

#定义一个数组A
A=(1 2 3 4 5 6)#打印数组元素对应的值
echo ${A[@]}
#1 2 3 4 5 6#将4号元素对应的值5修改为100
echo ${A[@]/5/100}#将4号元素对应的值6修改为200
echo ${A[@]/6/200}

6、数组删除

#定义一个数组A
A=(1 2 3 4 5 6)#删除数组中的指定的3号元素
unset A[3]#删除数组
unset ${A[*]}
unset A

三、Shell脚本调试

在Shell脚本开发中,经常碰到一些规范方面的问题,例如忘了使用引号或在if语句末尾处忘记加fi结束。要注意把复杂的脚本简单化,要思路清晰,并且分段实现。当执行脚本时出现错误后,不要只看那些提示的错误行,而是要观察整个相关的代码段。

为避免编写的脚本出错,除了在编写脚本时注意书写规范,排除语法错误,更重要的是利用调试脚本工具来调试脚本。echo命令是最有用的调试脚本工具之一,一般在可能出现问题的脚本中加入echo命令,采用的是分段排查的方式

除了echo命令之外,bash Shell也有相应参数可以调试脚本

sh [-nvx] 脚本名
-n不会执行该脚本,仅查询脚本语法是否有问题,如果没有语法问题就不显示任何内容,如果有问题会提示报错
-v在执行脚本时,先将脚本的内容输出到屏幕上然后执行脚本,如果有错误,也会给出错误提示
-x

将执行的脚本内容输出到屏幕上,这个是对调试很有用的参数

#!/bin/bash
set -x #开启调试
#定义 sum 函数
sum() {
read -p "请输入第一个数字:" A
#检查是否为有效数字
if ! [[ $A =~ ^[0-9]+$  ]]
thenecho "这不是一个有效数字,请重新输入"return 1
firead -p "请输入第二个数字:" B
if ! [[ $B =~ ^[0-9]+$  ]]
thenecho "这不是一个有效数字,请重新输入"return 1
fi
set +x #关闭调试
#计算两数之和
result=$((A + B))
echo "两数之和是:$result"
}
#调用函数
sum

总结:

函数:函数是Shell脚本中组织代码、提高复用性的重要手段。通过将一系列指令封装成函数,可以避免代码重复,使脚本更加简洁易读。函数的定义与调用简单直观,支持参数传递和递归调用,为模块化开发提供了便利。

数组:作为Shell脚本中的一种重要数据结构,数组支持存储多个值,并提供了丰富的操作方法,如获取数组长度、读取和赋值、遍历、切片、替换和删除元素等。这些功能在处理一组相关数据时非常有用。

调试与测试:在Shell脚本编写过程中,调试与测试是确保脚本正确运行的关键环节。通过使用echo命令和bash的调试参数(-n、-v、-x),可以方便地定位和解决问题,提高脚本的稳健性

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

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

相关文章

Baumer工业相机堡盟工业相机的工业视觉中为什么偏爱“黑白相机”

Baumer工业相机堡盟工业相机的工业视觉中为什么偏爱“黑白相机” Baumer工业相机​为什么偏爱“黑白相机”?​工业视觉中为什么倾向于多使用黑白相机黑白相机在工业视觉中的应用场景有哪些? Baumer工业相机 工业相机是常用与工业视觉领域的常用专业视觉…

MiM: Mask in Mask Self-SupervisedPre-Training for 3D Medical Image Analysis

Abstract Vision Transformer在3D医学图像分析的自监督学习(Self-Supervised Learning,SSL)中展现了卓越的性能。掩码自编码器(Masked Auto-Encoder,MAE)用于特征预训练,可以进一步释放ViT在各…

SQL注入的绕过方式

1.注释与空白符绕过 利用#,--,/**/替代被过滤的注释符 利用%09(Tab),%0A(换行) ,/**/代替空格:如union%0Aselect%0A1,2,3 2.编码绕过: URL编码,双重编码,十六进制编码,Unicode编…

数据加密方式(对称加密/非对称加密 /数字签名/证书)

文章目录 数据加密方式常用加密方式对比哈希算法(Hashing)哈希算法的特点常见的哈希算法哈希算法的应用哈希与加密的区别哈希算法的安全性问题 对称加密(Symmetric Encryption)工作原理主要特点常见的对称加密算法优缺点 非对称加…

UnityDots学习(五)

此篇开始研究实际应用到项目或个人Demo中。参考国外CodeMonkey的RTS包含一些基础API应用。 前言 游戏不必100%使用Dots完全实现。因为面向组件开发一个功能复杂度和调试都比面向对象要更难。对于某些模块,比如UI,事件管理系统,网络等&#…

移动端前端开发中常用的css

在开发移动端项目的时候,很多样式都是相同的,比如说图标大小,头像大小,页面底部保存(添加按钮),项目主体颜色等等,对于这些在项目中常用到的,通常都会写在公共样式中(pub…

Vue3 中 ref 与 reactive 的区别及底层原理详解

一、核心区别 1. 数据类型与使用场景 • ref 可定义基本类型(字符串、数字、布尔值)和对象类型的响应式数据。对于对象类型,ref 内部会自动调用 reactive 将其转换为响应式对象。 语法特点:需通过 .value 访问或修改数据&#…

AGV导航控制器技术方案——基于EFISH-SBC-RK3576/SAIL-RK3576的国产化革新‌(新一代工业级自主可控解决方案)‌

一、方案核心架构 ‌1. 硬件拓扑设计‌ ‌主控单元‌:SAIL-RK3576核心板(八核A72A53M0异构架构)‌传感器层‌: 双激光雷达(RS-LiDAR-16线 SICK TIM240)9轴IMU(BMI088) 轮式编码器&…

AI 辅助生成原型图

AI 辅助生成原型图 一、HTML 转设计稿工具介绍 网页转设计稿工具 使用 MasterGo 的 html-to-mastergo 插件可将网页转为设计稿,支持: 任意在线 HTML 文件(通过将 AI 生成的 UI 发布为在线页,可通过 Vercel 实现)离…

从零打造个人博客静态页面与TodoList应用:前端开发实战指南

前言 在当今数字时代,拥有个人博客和高效的任务管理工具已成为开发者展示自我和提升生产力的标配。本文将带你从零开始,通过纯前端技术实现一个兼具个人博客静态页面和TodoList任务管理功能的综合应用。无论你是前端新手还是希望巩固基础的中级开发者&a…

工作流与n8n:自动化技术的演进与开源工具的核心地位

第一章 工作流的基础理论介绍 1.1 工作流的定义与核心要素 工作流(Workflow)是指一系列相互衔接、自动化的业务活动或任务,其核心在于通过规则驱动的流程设计,实现跨系统、跨角色的协同作业。根据国际工作流管理联盟&#xff08…

WordPress插件:WPJAM Basic优化设置

WPJAM Basic 插件的「优化设置」是我爱水煮鱼博客多年使用 WordPress 的经验而整理的各类优化设置。 一、功能屏蔽 功能屏蔽就是屏蔽一些WordPress中用不上、难用的功能,目前的支持屏蔽以下功能: (1)屏蔽文章修订功能 文章修…

Spring AI 入门(持续更新)

介绍 Spring AI 是 Spring 项目中一个面向 AI 应用的模块&#xff0c;旨在通过集成开源框架、提供标准化的工具和便捷的开发体验&#xff0c;加速 AI 应用程序的构建和部署。 依赖 <!-- 基于 WebFlux 的响应式 SSE 传输 --> <dependency><groupId>org.spr…

c/c++日志库初识

C/C日志库&#xff1a;从入门到实践的深度指南 在软件开发的世界里&#xff0c;日志&#xff08;Logging&#xff09;扮演着一个沉默却至关重要的角色。它像是飞行记录仪的“黑匣子”&#xff0c;记录着应用程序运行时的关键信息&#xff0c;帮助开发者在问题发生时追溯根源&a…

C 语言图形编程 | 界面 / 动画 / 字符特效

注&#xff1a;本文为 “C 语言图形编程” 相关文章合辑。 略作重排&#xff0c;如有内容异常&#xff0c;请看原文。 C 语言图形化界面——含图形、按钮、鼠标、进度条等部件制作&#xff08;带详细代码、讲解及注释&#xff09; 非线性光学元件于 2020-02-15 09:42:37 发布…

开发狂飙VS稳定刹车:Utility Tree如何让架构决策“快而不失控”

大家好&#xff0c;我是沛哥儿。 在软件技术架构的世界里&#xff0c;架构师们常常面临灵魂拷问&#xff1a;高并发和低成本哪个优先级更高&#xff1f; 功能迭代速度和系统稳定性该如何平衡&#xff1f; 当多个质量属性相互冲突时&#xff0c;该如何做出科学决策&#xff1f; …

SCI论文图数据提取软件——GetData Graph Digitizer

在写综述或者毕业论文的时候一般会引用前人的文献数据图&#xff0c;但是直接截图获取来的数据图通常质量都不太高。因此我们需要从新画一张图&#xff0c;可以通过origin绘图来实现&#xff0c;今天介绍一个新的软件GetData Graph Digitizer 感谢下面博主分享的破解安装教程 …

深入探索 Apache Spark:从初识到集群运行原理

深入探索 Apache Spark&#xff1a;从初识到集群运行原理 在当今大数据时代&#xff0c;数据如同奔涌的河流&#xff0c;蕴藏着巨大的价值。如何高效地处理和分析这些海量数据&#xff0c;成为各行各业关注的焦点。Apache Spark 正是为此而生的强大引擎&#xff0c;它以其卓越…

场景可视化与数据编辑器:构建数据应用情境​

场景可视化是将数据与特定的应用场景相结合&#xff0c;借助数据编辑器对数据进行灵活处理和调整&#xff0c;通过模拟和展示真实场景&#xff0c;使企业能够更直观地理解数据在实际业务中的应用和影响&#xff0c;为企业的决策和运营提供有力支持。它能够将抽象的数据转化为具…

攻防世界-php伪协议和文件包含

fileinclude 可以看到正常回显里面显示lan参数有cookie值表示为language 然后进行一个判断&#xff0c;如果参数不是等于英语&#xff0c;就加上.php&#xff0c;那我们就可以在前面进行注入一个参数&#xff0c;即flag&#xff0c; payload&#xff1a;COOKIE:languageflag …