• shell之函数和数组(案例分析)


    一、shell函数

    1、函数的作用

    函数的定义

    function  函数名 {
           command
    }
    
    或者----------------------
    
    函数名 () {
         command
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    函数定义完之后并不会自动执行,需要调用才行,好处在于可以写一段功能代码作为函数,有需要就直接调用。定义的时候哪怕出现语法错误也没关系,不调用就不会报错,当然我们写函数最终目的还是为了调用,为了实现某个功能块。

    函数的返回值

    return表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值

    使用原则:

    • 函数一结束就取返回值,因为$?变量值返回执行的最后一条命令的退出状态码
    • 退出状态码必须0~255,超出时值将为取余256(例如:返回码为444,那么将444%256)

    2、函数的调用

    直接在脚本里定义函数的代码块写函数名即可完成调用

    • 案例:简单的函数调用

    在这里插入图片描述
    在这里插入图片描述

    注意:函数名必须是唯一的,如果先定义了一个,再用同样的名称定义第二个,那么第二个会覆盖第一个的功能,所以这里一定要注意不要重名!

    • 案例:相同函数名的调用
      在这里插入图片描述在这里插入图片描述

    注意:调用函数之前,必须先进行定义!就是说函数的调用必须在函数的后面。

    • 案例:函数调用顺序问题
    在其它函数中嵌套调用函数的情况,不可以直接写函数的值,便面无法识别,可以用反撇号引起来,相当于是调用函数的结果
    
    • 1

    在这里插入图片描述
    在这里插入图片描述

    • 案例:假如调用fun3放其中一个函数的前面

    在这里插入图片描述
    在这里插入图片描述

    注意:不一定要在脚本开头就定义函数,只要调用之前定义就可以

    案例:最后调用函数,将fun3函数放在其它两个函数中间

    在这里插入图片描述
    在这里插入图片描述

    案例:使用脚本编写手动安装yum源,需要用到函数的调用
    在这里插入图片描述

    2、return的用法

    • 终止一个函数
    • return命令允许带一个整形参数(0-255),这个整数将最为函数的“退出状态码”返回给调用这个函数的脚本,并且这个整数也被复制给变量$?
    • 如果没有return命令,函数将返回最后一个指令的退出状态

    案例:对比函数中添加与不添加return的区别

    • 不加return

    在这里插入图片描述
    在这里插入图片描述

    • 加return

    在这里插入图片描述

    在这里插入图片描述

    案例2:测试文件是否存在

    在这里插入图片描述
    在这里插入图片描述

    3、 函数的作用范围

    • 在shell脚本中函数的执行并不会开启一个新的子shell,而是仅在当前定义的shell环境中有效,如果shell脚本中的变量没有经过特殊设定,默认在整个脚本中都是有效的。

    • 在编写脚本时,有时需要将变量的值限定在函数内部,可以通过内置命令local来实现,函数内部变量的使用,可以避免函数内外同时出现同名变量对脚本结果的影响

    shell脚本中变量默认全局有效
    local命令:将变量限定在函数内部使用
    
    • 1
    • 2

    案例:函数内和函数外定义相同变量

    在这里插入图片描述
    在这里插入图片描述

    上述脚本中fun1函数内部使用了local命令设置变量num,其作用是将变量num限定在函数内部,fun1函数外部同样定义了变量num,内部变量num和全局变量互不影响。脚本执行先调用了函数fun1,函数内部变量num为10,所以输出10,调完函数,变量num赋值为100,所以有输出100

    4、函数的参数

    在shell中,调用函数时可以向其传递参数,在函数体内部,通过$n的形式来获取参数值,例如,$1表示第一个参数,$2表示第二个参数,就是使用位置参数来实现参数传递。

    案例:调用函数时输入位置参数

    在这里插入图片描述
    在这里插入图片描述

    案例:用户输入位置参数

    在这里插入图片描述
    在这里插入图片描述

    案例:根据用户输入的值,求出奇数和以及偶数和,求和用函数来写

    在这里插入图片描述
    在这里插入图片描述

    5、函数的递归调用

    函数自己调用自己

    案例1:列出目录内文件列表,目录用蓝色表示,文件显示层级关系

    在这里插入图片描述

    在这里插入图片描述

    案例2:计算5的阶乘

    • 平常计算阶乘

    在这里插入图片描述

    在这里插入图片描述

    • 使用递归结算阶乘

    在这里插入图片描述

    使用 sh -x 脚本名称 ,来查看执行步骤

    在这里插入图片描述

    在这里插入图片描述

    二、数组

    数组是存放相同类型数据的集合,在内存中开辟了连续的空间,通常配合循环使用

    1、数组的分类

    普通数组: 不需要申明直接定义,下标索引只能是整数

    关联数组: 需要用declare -A 申明,否则系统不识别,索引可以是字符串

    2、数组的定义方式

    2.1 第一种

    直接把要加入数组的元素用小括号括起来,中间用空格分开

    格式:  数组名=(value0    value 1    value2)
    
    例如:num=(10 20 30 40)
    
    • 1
    • 2
    • 3

    2.2 第二种

    精确的给每一个下表索引定义一个值加入数组,索引数字可以不连续

    格式:   数组名=([0]=value   [1]=value  [2]=value....)
    
    例如:num=([0]=10 [1]=20 [2]=30 [3]=40)
    
    • 1
    • 2
    • 3

    2.3 第三种

    先把要加入数组的元素全部先复制给一个变量,然后引用这个变量加入到数组

    格式:   数组=($列表名)
            变量= "value0 value1 value2 value3"
            
    例如:
            list= "10 20 30 40"
            num=($list)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.4 第四种

    根据下表定义

    格式:    数组名[0]="value"
             数组名[1]="value"
             数组名[2]="value"
    例如:    num[0]="10"
             num[1]="20"
             num[2]="30"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3、获取数组的长度和元素

    获取数组的所有元素的总数

    在这里插入图片描述

    获取数组所有元素的列表内容

    在这里插入图片描述

    根据下标获取数组元素的内容

    在这里插入图片描述

    根据下标获取元素的长度

    在这里插入图片描述

    总结

    定义数组最简单的办法就是:num=(10 20 30 40)
    
    读取数组中的全部长度使用:echo ${#num[*/@]}
       读取数组中的下标对应的元素长度: echo ${#num[下标]}
       
    读取数组中的全部内容使用:echo ${num[*/@]}
       读取数组中的下标对应的元素内容: echo ${num[下标]}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4、数组的遍历

    使用for循环。遍历输出数组中的每一个元素

    在这里插入图片描述
    在这里插入图片描述

    5、数组元素的切片(提取)

    就是将数组中的元素输出的时候,进行指定哪一块元素进行输出。依靠索引进行查找到元素的位置。

    在这里插入图片描述

    6、数组元素的替换

    在这里插入图片描述

    在这里插入图片描述

    7、数组元素的删除

    删除整个数组

    在这里插入图片描述

    删除数组中单个元素

    在这里插入图片描述

    9、冒泡排序

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

    基本思想

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

    算法思路

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

    案例:用冒泡排序对数组元素进行排序(最小数放前面)

    注意:此方法是将第一个数和后面的每一个数进行比较,然后第一个数为最小的数,然后第二个数和后面的每一个数进行比较,然后第二个数为倒数第二小的数,依次比较,循环结束,即可完成排序。
    在这里插入图片描述

    在这里插入图片描述

    案例2:用冒泡排序对数组元素进行排序(最大数放后面)

    注意:第一个数个第二数进行比较,大的放第二个数的位置,第二个和第三个数进行比较,大的放第三个数的位置,直到最后一个数为最大数,然后又重新循环。直到循环结束,排序完成。

    在这里插入图片描述
    在这里插入图片描述

    案例:实现用户输入数组中的元素,然后将数组内容进行降序排列

    代码如下:

    #!/bin/bash
    #定义数组中的元素
    i=0
    while true
    do
      read -p "请输入数组中的元素(数字),截止输入stop:" ack
    #用户输入的为stop,那就不再进行获取数组元素
          if [ $ack = "stop" ];then
             break
          fi
    #将用户输入的变量赋值到数组中
          num[$i]=$ack
          let i++
    done
    lh=${#num[*]}
    echo  "你输入的数组为:${num[*]},长度为:$lh"
    #下面进行冒泡排序
    for ((i=1;i<${#num[*]};i++))
    do
         for ((j=0;j<$lh-$i;j++))
          do
             first=${num[$j]}
                b=$[j+1]
             sec=${num[$b]}
              if [ $first -lt $sec ];then
                  temp=$first
                  num[$j]=$sec
                  num[$b]=$temp
              fi
          done
    done
    echo "排序后的数组为:${num[*]}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    在这里插入图片描述
    在这里插入图片描述

    三、总结

    函数

    • 函数的作用: 就是实现一个功能块,然后进行调用,函数名不能重复
    • 函数中可以使用return进行返回一个状态码 ,可以根据状态码查看函数的运行效果
    • 函数中定义变量,可以 使用local关键字进行定义成局部变量 ,局部变量只能在函数中使用,不会与shell环境中的其它相同变量名冲突
    • 函数的参数可以使用位置参数进行传参 ,在调用时可以直接输入位置参数的值。也可以调用时再定义位置变量,然后通过获取用户输入的值来传给函数中的变量。

    数组

    • 数组的定义方式有多种, 最常见的就是函数名=(元素1 元素2 元素3)

    • 查看数组的长度: ${#数组名[*或@]},查看函数的元素内容: ${数组名[*或@]}

    • 数组中元素的赋值,最常用的赋值为: 数组名[下标]=元素值

    • 数组的切片:切片的意思就是将数组元素内容按照设定的内容进行输出

      • 格式:echo ${数组名[*]:下标:需要打印的几个元素值}

      • 例如:将数组内容的第二个元素开始的3个元素输出

      • echo ${num[*]:1:3}

    • 数组的替换:只是在输出的时候进行替换 (注意:在替换的时候,它找到内容是数组元素中的内容)

      • 格式:echo ${[*]/匹配的内容/替换后的内容} (仅替换每个元素的第一个匹配项)

      • 例如:将输入中的内容3换成10

      • echo ${num[*]/3/10}

  • 相关阅读:
    通过数据可观测性进行价值工程和数据成本优化
    4 zookeeper集群和基本命令
    输入一批数,找中位数
    Nginx基础篇-Nginx的WEB模块~连接状态
    stream流
    MarkBERT: 一种通过简单添加词边界的方法来增强预训练模型
    【翻译】Kingfisher 官方指南 Cheet Sheet
    用 setTimeout 来实现 setInterval
    sheng的学习笔记-【中英】【吴恩达课后测验】Course 1 - 神经网络和深度学习 - 第四周测验
    Hadoop-2.5.2平台环境搭建遇到的问题
  • 原文地址:https://blog.csdn.net/m0_57515995/article/details/125609396