shell 脚本的函数和数组

函数

—— 封装的一个公式:sin、cos、tan

—— 函数为脚本的别名

—— 函数就是一个功能模块,在函数中写执行的命令即可;使用函数可以避免代码重复,增加可读性,简化脚本,使用函数可以将大的工程分割为若干小的功能模块,代码的可读性更强

—— 函数由函数名和函数体组成

—— 函数一定要先定义,才能使用

—— 帮助:help function

函数的用法

注:一定要先给函数定义,才能执行函数

查看函数
declare 命令

—— declare -F :查看函数列表

—— declare -f __函数名 :查找指定函数名;两个下划线

函数的定义

—— 格式1:自定义函数名 () {

脚本;命令序列

}

—— 格式2:function 自定义函数名 {

脚本;命令序列

}

—— 格式3:function 自定义函数名 (){

脚本;命令序列

}

例
格式1    #一般用此格式
[root@localhost opt]# han () { echo "hello"; }
#定义一个函数 han 为标准输出 hello
[root@localhost opt]# han
hello    #执行此函数,显示结果

格式2
[root@localhost opt]# function han { echo "hello"; }
[root@localhost opt]# han
hello

格式3
[root@localhost opt]# function han () { echo "hello"; }
[root@localhost opt]# han
hello

删除函数
unset 命令

—— unset 函数名

例
#先定义一个函数,并验证是否能使用
[root@localhost opt]# han () { echo "hello"; }
[root@localhost opt]# han
hello

[root@localhost opt]# unset han      #删除函数
[root@localhost opt]# han
bash: han: 未找到命令...
#再次使用函数,验证是否删除;删除成功

定义函数变量的作用范围

local

—— 加此关键词,可以固定函数的变量范围,使其只能在函数内运行

export

—— 让子shell 继承变量


例
[root@localhost opt]# name=吴彦祖       #定义一个变量name为吴彦祖
[root@localhost opt]# echo $name       #验证
吴彦祖
[root@localhost opt]# id () { name=彭于晏;echo $name; }
#定义一个函数id,让其中变量name输出结果为彭于晏
[root@localhost opt]# id               #验证
彭于晏
[root@localhost opt]# echo $name
彭于晏
 #此时输出变量name已经被函数id所影响
[root@localhost opt]# unset id
[root@localhost opt]# echo $name
彭于晏
#就算删除函数id,变量name已经被更改
[root@localhost opt]# name=吴彦祖        #重新定义name
[root@localhost opt]# echo $name        #验证
吴彦祖
[root@localhost opt]# id () { local name=彭于晏;echo $name; }
#使用命令 local,限制变量参数,使其只能在函数中执行
[root@localhost opt]# id                #验证
彭于晏
[root@localhost opt]# echo $name        #验证,此时变量name不会被函数id影响
吴彦祖

函数的返回值

return

—— 自定义 返回值 0 -- 255

—— 如果使用函数,那么 $? 那么使用就会受限,可以使用 return 自定义 $? 的返回值,来判断函数中的命令是否成功

—— 函数一结束就取返回值,因为 $? 变量只返回执行的最后一条命令的退出返回码

—— 退出码必须是0-255,超出的值将为除以256取余

例
[root@localhost opt]# text () { echo "hello"; }
#定义一个函数
[root@localhost opt]# text
hello
[root@localhost opt]# echo $?
0
#此时返回值为0
[root@localhost opt]# text () { echo "hello";return 250; }
#更改返回值为250
[root@localhost opt]# text
hello
[root@localhost opt]# echo $?
250
#此时返回值已经被更改为250

函数的传递参

脚本
#!/bin/bash
sum () {
echo " $1 "     #识别第一个字符串
echo " $2 "     #识别第二个字符串
#识别两个字符串
}
sum $2 $1
#这后面的$2和$1,代表的是跟在脚本后面的字符串的顺序;此处就是设定将第二个字符串放在第一位,将第一个字符串放在第二位

显示结果
[root@localhost opt]# bash j.sh 1 9
 9 
 1 

需要注意

—— 脚本的 $1 $2 和函数的 $1 $2 ,是没有关系的

—— 函数的 $1 $2 是指跟在函数后面的值

递归函数

—— 函数的本质就是一个程序,每开一个进程都会消耗资源,无限的开自己死循环就会造成资源的无限占用形成病毒

—— 函数调用自己本身的函数

—— 必须要有结束函数的语句,防止死循环

阶乘函数

—— 一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0和1的阶乘为1,自然数n的

—— 阶乘写作 n! =1×2×3×...×n

—— 阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n n!=n(n-1)(n-2)...1 n(n-1)! = n(n-1)(n-2)!

脚本举例:此脚本作用是计算任意数值的阶乘
#!/bin/bash
fact () {
if [ $1 -eq 0  -o  $1 -eq 1 ]
then
   echo 1
else
   echo $[$1* $(fact $[$1-1])]
#这里将 $[$1-1] 的值再次使用函数 fact 进行执行
#此处 * 为乘
fi
}
fact $1

结果展示
[root@localhost opt]# bash digui.sh 5
120
#5的阶乘为120

函数的文件

—— 专门存放函数的文件

—— . 绝对路径的文件名 函数名:从存放函数的文件中,提取使用指定函数(. 可以用 source 代替)


数组

—— 数据的集合称为数组

  • 普通数组,普通数组可以不事先声明,直接使用;下标只能是数值

  • 关联数组,关联数组必须先声明,再使用;下标可以自定义任意字符串

  • 变量:存储单个元素的内存空间

  • 数组:存储多个元素的连续的内存空间,相当于多个变量的集合

—— 数组名和索引

  • 索引的编号从0开始,属于数值索引

  • 索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,bash 4.0版本之后开始支持

  • bash的数组支持稀疏格式(索引不连续)

数组的使用

—— 一定要先声明数组

daclare -a 普通数组(不需要手动声明,系统帮你声明了)

—— 关联数组一定要手动声明

declare -A 数组名

定义数组

—— 自定义数组名=(数组值中间用空格隔开)

单个调用
echo作用
${a[0]}调用第一个值
${a[1]}调用第二个值
${a[2]}调用第三个值
…………
${a[n]}调用第n个值
全部调用
echo作用
${a[@]} 或者 ${a[*]}显示所有结果
${#a[@]} 或者 ${#a[*]}统计个数
${!a[@]} 或者 ${!a[*]}显示所有下标

数组切片

—— 格式:echo ${自定义数组名[@或*]:自定义数字:自定义数字}

—— 注意:以 “:” 为分隔符

例
[root@localhost opt]# a=(1 2 3 4 5)
[root@localhost opt]# echo ${a[@]:1:3}
2 3 4
#从第一个开始并跳过第一个,到后三个结束

数组替换

—— 格式:echo ${自定义数组名[@或*]/查找的目标字符/替换的字符}

—— 注意:以 “/” 为分隔符

例
[root@localhost opt]# a=(1 2 3 4 5)
[root@localhost opt]# echo ${a[@]/2/hi}
1 hi 3 4 5
#查找a数组中第二个字符串,并替换成hi

数组删除

—— 格式:unset 数组名 //删除该数组

—— 格式:unset 数组名[n] //选择数组中的第 n 个删除;从0开始,0代表第一个字符

例
[root@localhost opt]# a=(1 2 3 4 5)
[root@localhost opt]# echo ${a[*]}
1 2 3 4 5
[root@localhost opt]# unset a[2]            #删除该数组中第三个字符   
[root@localhost opt]# echo ${a[*]}          #验证 
1 2 4 5
[root@localhost opt]# unset a               #删除该数组
[root@localhost opt]# echo ${a[*]}
#不会显示任何东西

冒泡排序

—— 一种数组排序算法

—— 类似气泡上涌的动作,会将数据在数组中从小到大或者从大到小不断的向前移动

—— 基本思想:冒泡排序的基本思想是对比相邻的两个元素值,如果满足条件就交换元素值,把较小的元素移动到数组前面,把大的元素移动到数组后面(也就是交换两个元素的位置),这样较小的元素就像气泡一样从底部上升到顶部

—— 算法思路:冒泡算法由双层循环实现,其中外部循环用于控制排序轮数,一般为要排序的数组长度减1次,因为最后一次循环只剩下一个数组元素,不需要对比,同时数组已经完成排序了,而内部循环主要用于对比数组中每个相邻元素的大小,以确定是否交换位置,对比和交换次数随排序轮数而减少

脚本举例:此脚本是随机生成十个不同的数字并进行从小到大排序
#!/bin/bash
for  i  in {0..9}
do
a[$i]=$RANDOM
done
#生成一个拥有十个随机数的数组
echo "原始数组: ${a[@]}"

l=${#a[@]}
#定义变量l 等同于数组的总个数;此处 l=10
for((i=1;i<$l;i++))
#需要进行比较的次数
do
   for ((j=0;j<$l-$i;j++))
   #相邻的数字,需要比较的次数
   do
   first=${a[$j]}
   #数组的第 n个数
   k=$[$j+1]
   #数组的 n+1大小的下标
   second=${a[$k]}
   #数组的第 n+1个数
   if [ $first  -gt  $second ]
   then
   temp=$first
   a[$j]=$second
   a[$k]=$temp
   #该三行是将两个数字进行更换位置
   fi
   done
done

echo "从小到大:  ${a[@]}" 

脚本举例

比较随机数字的数组大小
#!/bin/bash
for a in {0..9}
do
   b[$a]=$RANDOM
   [ $a -eq 0 ] && min=${b[0]} && max=${b[0]}
   [ ${b[$a]} -gt $max ] && max=${b[$a]}
   [ ${b[$a]} -lt $min ] && min=${b[$a]}
done

echo "数组: ${b[*]}"
echo "最大值: $max"
echo "最小值: $min"

补充命令

scp 脚本名 目标ip

—— 将脚本发送给指定虚拟机

declare 命令补充

—— declare +/- 选项 变量名

选项作用
-赋予变量类型属性
+取消变量的类型属性
-a将变量声明为数组型
-i将变量声明为整数型
-x将变量声明为环境变量
-r将变量声明为只读变量
-p查看变量的被声明的类型

eval 命令

—— 格式:eval()

—— 注释:将任意字符串当成有效的表达式来求值并返回计算结果;如果参数不是字符串类型,则直接返回参数;需要注意的是,使用 eval() 函数时需要谨慎,因为它可以执行任意代码,存在一定的安全风险

显示颜色的命令

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

教育数字化转型:塑造未来学习新范式

在国家教育数字化战略行动指引下&#xff0c;我国正积极推动数字化赋能教育高质量发展&#xff0c;以塑造教育发展的新优势。如今&#xff0c;随着科技新基建的普及和数字化赋能教育的深入推进&#xff0c;未来的教育模型正在逐渐形成。 在新的教育模型中&#xff0c;数字化学…

【python海洋专题四十七】风速的风羽图

【python海洋专题四十七】风速的风羽图 图片 往期推荐 图片 【python海洋专题一】查看数据nc文件的属性并输出属性到txt文件 【python海洋专题二】读取水深nc文件并水深地形图 【python海洋专题三】图像修饰之画布和坐标轴 【Python海洋专题四】之水深地图图像修饰 【Pyth…

在一个页面里向两张表里插入内容时,有一些复杂的BUG简单化

向两张表里插入内容时&#xff0c;有一些复杂的BUG简单化 当在第一张表里的页面操作&#xff0c;在第一张表查询结果的页面进行编辑&#xff0c;在编辑的时候需要对第二张表里和第一张表都保存内容&#xff0c;而且插入之后两张表的id关联着&#xff0c;这个时候这张表的id就不…

IntelliJ IDEA 16创建Web项目

首先要理解一个概念&#xff1a;在IntelliJ IDEA中“new Project”相当于eclipse中的工作空间&#xff08;Workspace&#xff09;&#xff0c;而“new Module”相当于eclipse中的工程&#xff08;Project&#xff09;。以下均采用Intellij的说法&#xff0c;请自行对照转换理解…

C语言——从键盘输人一个表示年份的整数,判断该年份是否为闰年,并显示判断结果。

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int year 0;printf("请输入年份&#xff1a;");scanf("%d",&year);if((year%4 0) && (year%100!0) || (year%400 0)){printf("%d是闰年\n",year);}else{p…

Using PeopleCode in Application Engine Programs在应用引擎程序中使用PeopleCode

This section provides an overview of PeopleCode and Application Engine programs and discusses how to: 本节概述了PeopleCode和应用程序引擎程序&#xff0c;并讨论了如何: Decide when to use PeopleCode.决定何时使用PeopleCode。Consider the program environment.考…

队列的实现和OJ练习(c语言)

目录 概念 队列的实现 利用结构体存放队列结构 为什么单链表不使用这种方法&#xff1f; 初始化队列 小提示&#xff1a; 队尾入队列 队头出队列 获取队头元素 获取队尾元素 获取队列中有效元素个数 检测队列是否为空 销毁队列 最终代码 循环队列 队列的OJ题 …

git clone -mirror 和 git clone 的区别

目录 前言两则区别git clone --mirrorgit clone 获取到的文件有什么不同瘦身仓库如何选择结语开源项目 前言 Git是一款强大的版本控制系统&#xff0c;通过Git可以方便地管理代码的版本和协作开发。在使用Git时&#xff0c;常见的操作之一就是通过git clone命令将远程仓库克隆…

SHAP - 机器学习模型可解释性工具

github地址&#xff1a;shap/docs/index.rst at master shap/shap (github.com) SHAP使用文档&#xff1a;欢迎使用 SHAP 文档 — SHAP 最新文档 SHAP介绍 SHAP&#xff08;SHapley Additive exPlanations&#xff09;是一种用于解释预测结果的方法&#xff0c;它基于Shapley…

好的程序员有什么特质呢?

程序员想要提升自己&#xff0c;一定要关注到工作中的方方面面。而一个好的程序员&#xff0c;一般都有这些特质&#xff1a; 弱者抱怨环境&#xff0c;强者改变环境 不要试图通过抱怨环境来获得工作环境上的改变&#xff0c;这不仅不会给你带来任何实质性的改变&#xff0c;…

一文详解Vue生命周期

Vue是一种流行的用于构建用户界面的渐进式JavaScript框架。Vue框架在开发过程中&#xff0c;特别强调对生命周期的理解和管理。通过使用生命周期钩子函数&#xff0c;开发者能够精确地控制Vue实例的创建、挂载、更新以及销毁过程。本文将对Vue的生命周期进行详细的介绍&#xf…

Nginx模块开发之http handler实现流量统计(1)

文章目录 一、handler简介二、Nginx handler模块开发2.1、示例代码2.2、编写config文件2.3、编译模块到Nginx源码中2.4、修改conf文件2.5、执行效果 三、Nginx的热更新总结 一、handler简介 Handler模块就是接受来自客户端的请求并产生输出的模块。 配置文件中使用location指令…

微软发布最新.NET 8长期支持版本,云计算、AI应用支持再强化

11 月 15 日开始的为期三天的 .NET Conf 在线活动的开幕日上&#xff0c;.NET 8作为微软的开源跨平台开发平台正式发布。.NET 团队着重强调云、性能、全栈 Blazor、AI 和 .NET MAUI 是.NET 8的主要亮点。.NET团队在 .NET Conf 2023 [1]活动开幕式上表示&#xff1a;“通过这个版…

JSP过滤器和监听器

什么是过滤器 Servlet过滤器与Servlet十分相似&#xff0c;但它具有拦截客户端&#xff08;浏览器&#xff09;请求的功能&#xff0c;Servlet过滤器可以改变请求中的内容&#xff0c;来满足实际开发中的需要。 对于程序开发人员而言&#xff0c;过滤器实质就是在Web应用服务器…

不会代码也能拿高薪?掌握面试法宝,轻松10000+

快速排序&#xff08;Quicksort&#xff09;是对冒泡排序的一种改进。 快速排序由 C.A.R.Hoare 在 1962 年提出。 它的基本思想是&#xff1a;通过一趟排序将要排序的数据分割成独立的两部分&#xff0c;其中一部分的所有数据都比另外一部分的所有数据都要小&#xff0c;然后…

代码随想录算法训练营第五十二天|1143.最长公共子序列 1035.不相交的线 53. 最大子序和

文档讲解&#xff1a;代码随想录 视频讲解&#xff1a;代码随想录B站账号 状态&#xff1a;看了视频题解和文章解析后做出来了 1143.最长公共子序列 class Solution:def longestCommonSubsequence(self, text1: str, text2: str) -> int:dp [[0] * (len(text2) 1) for _ i…

Redisson分布式锁源码解析、集群环境存在的问题

一、使用Redisson步骤 Redisson各个锁基本所用Redisson各个锁基本所用Redisson各个锁基本所用 二、源码解析 lock锁 1&#xff09; 基本思想&#xff1a; lock有两种方法 一种是空参 另一种是带参 * 空参方法&#xff1a;会默认调用看门狗的过期时间30*1000&…

从Discord的做法中学习 — 使用Golang进行请求合并

正如你可能之前看到的&#xff0c;Discord去年发布了一篇有价值的文章&#xff0c;讨论了他们成功存储了数万亿条消息。虽然有很多关于这篇文章的YouTube视频和文章&#xff0c;但我认为这篇文章中一个名为“数据服务为数据服务”的部分没有得到足够的关注。在这篇文章中&#…

redis运维(十九)redis 的扩展应用 lua(一)

一 redis 的扩展应用 lua redis如何保证原子操作 说明&#xff1a;引入lua脚本,核心解决原子性问题 ① redis为什么引入lua? lua脚本本身体积小,启动速度快 ② redis引入lua的优势 小结&#xff1a; 类似自定义redis命令 ③ redis中如何使用lua ④ EVAL 说明&#…

【性能优化】JVM调优与写出JVM友好高效的代码

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;2022年度博客之星全国TOP3&#xff0c;专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化&#xff0c;文章内容兼具广度、深度、大厂技术方案&#xff0c;对待技术喜欢推理加验证&#xff0c;就职于…