Shell编程之函数和数组 (超详细)

函数和数组

  • 一、函数
    • 1.1 函数概述
      • 1.1.1 定义和优点
      • 1.1.2 函数使用注意事项
    • 1.2 函数的相关操作
      • 1.2.1 定义函数
      • 1.2.2 查看函数
      • 1.2.3 调用函数
      • 1.2.4 传递参数
      • 1.2.5 函数的返回值
      • 1.2.6 删除函数
    • 1.3 函数的作用范围
    • 1.4 函数文件
    • 1.5 递归函数(重要)
    • 1.6 函数练习
      • 1.6.1 判断系统类型,安装httpd服务
      • 1.6.2 用递归函数计算正整数的阶乘
  • 二、数组
    • 2.1 为什么要用数组?
    • 2.2 定义数组的方法
    • 2.3 普通数组和关联数组
      • 2.3.1 普通数组
      • 2.3.2 关联数组
    • 2.4 引用数组的值
    • 2.5 数组相关操作
      • 2.5.1 数组遍历
      • 2.5.2 数组切片
      • 2.5.3 数组删除
      • 2.5.4 数组替换
    • 2.6 数据排序算法之冒泡排序
      • 2.6.1 概述
      • 2.6.2 应用实例之升序排序
    • 2.7 数组练习
      • 2.7.1 提取最大值
      • 2.7.2 自定义数组,提取最小值
      • 2.7.3 点名脚本

一、函数

1.1 函数概述

1.1.1 定义和优点

函数将命令序列按格式写在一起,方便重复使用命令序列。

1.1.2 函数使用注意事项

  • 同名函数后一个生效;

  • 调用函数之前先定义函数,如果调用写在定义函数前,则调用无法生效;

  • 每个函数是独立的

1.2 函数的相关操作

1.2.1 定义函数

方式一(推荐使用)

function_name() {
# 函数体
}

方式二

function function_name {
# 函数体
}

方式三

function function_name() {
# 函数体
}

在函数体中可以编写任意数量的命令和逻辑来实现函数的功能

1.2.2 查看函数

declare -F
#查看所有已定义的函数的函数名

declare -F func_name
#查看指定函数的函数名

在这里插入图片描述

declare -f
#查看所有已定义的函数的内容
declare -f func_name 
#查看指定函数的内容

Shell编程之函数和数组 (超详细)_第1张图片

1.2.3 调用函数

只有定义了函数,才能调用函数

#先定义函数
function_name() {
# 函数体
}

#调用函数
function_name

Shell编程之函数和数组 (超详细)_第2张图片

1.2.4 传递参数

在函数调用时传递参数给函数。
在函数体内部通过位置变量来引用传递给函数的参数。

test() {
    echo "Parameter 1: $1"
    echo "Parameter 2: $2"
}
test $1 $2 
.......注释.........................................................
test1 $1 $2
# 这两个位置变量 是脚本的位置变量,就是执行脚本时,输入的值

test1 () { 
}
#test1函数中的位置变量和脚本的位置变量相对独立
#如果 变成
#test1 $2 $1 
#那么 对于test1函数来说,函数的$1就是脚本的$2

1.2.5 函数的返回值

函数可以通过return语句设置返回值。

return 从函数中返回,用最后状态命令决定返回值
return 0 无错误返回
return 1-255 有错误返回

超过256的值,会和256相除取余数

返回值的作用:

  1. 对函数执行的结果进行判断和处理:函数可以返回不同的值来表示不同的执行状态或错误情况。

  2. 传递函数执行的结果给其他部分:函数的返回值可以被赋值给变量,能将函数的计算结果传递给其他命令或者再次使用。

  3. 作为脚本的退出状态码:根据不同的返回值来设置不同的退出状态码。

1.2.6 删除函数

unset function_name 
#从当前的 Shell 环境中删除指定的函数

Shell编程之函数和数组 (超详细)_第3张图片

1.3 函数的作用范围

函数在Shell脚本中仅在当前Shell环境中有效,脚本中的变量默认全局有效
使用local命令可以将变量限定在函数内部使用。
Shell编程之函数和数组 (超详细)_第4张图片

1.4 函数文件

将函数代码写入一个脚本文件,在需要的时候调用该脚本文件,相当于直接调用函数。
Shell脚本中使用函数文件时,需要写上函数文件的绝对路径

1.5 递归函数(重要)

递归归函数是指在函数体内调用自身的函数,用于需要重复执行相同或类似任务的场景。
编写递归函数时要确保设定递归的结束条件,以避免死循环

#简单的示例#

#!/bin/bash
# 定义递归函数
factorial() {
  if (( $1 <= 1 )); then
    echo 1
  else
    local prev=$(factorial $(( $1 - 1 )))
    echo $(( $1 * $prev ))
  fi
}

# 调用递归函数
read -p "输入一个正整数: " n
result=$(factorial $n)
echo "阶乘结果为: $result"

1.6 函数练习

1.6.1 判断系统类型,安装httpd服务

[ [ == ] ] #开启通配符
[ [ =~ ] ] #开启正则表达式 

#!/bin/bash 

os () {
if grep -qi 'centos'  /etc/os-release
then
echo "centos"
elif grep -qi 'ubunto' /etc/os-release
then
echo "ubuntu"
else
echo "不支持此系统"
fi
}
#调用函数
os

if [ `os` = centos ]
then
yum install -y httpd
elif [ `os` = ubuntu ]
then
apt install apache2 -y
else
echo " fail "
fi

Shell编程之函数和数组 (超详细)_第5张图片
Shell编程之函数和数组 (超详细)_第6张图片

#补充知识
#ubuntu系统 

apt update #更新源?
apt install apache2#装httpd ,在ubuntu中,httpd服务就是apache2
dpkg -s apache2#看看有没有装
apt remove  #移除

1.6.2 用递归函数计算正整数的阶乘

#交互式

#!/bin/bash
read -p "请输入一个数:" num
fact() {
local n=$1
if [ $n -eq 0 ]; then
echo 1
elif [ $n -eq 1 ]; then
echo 1
else
local x=$[$n-1]
local result=$(fact $x)
echo $[$n * $result]
fi
}
result=$(fact $num)
echo "阶乘结果为:$result"                                                                           

Shell编程之函数和数组 (超详细)_第7张图片

二、数组

2.1 为什么要用数组?

数组是一种数据结构,用于存储一组相同类型的元素
数组是一个连续的内存区域,元素在内存中按照顺序存储,每个元素可以通过索引访问,索引从0开始,逐个递增。

数组可以存储各种类型的数据,例如整数、浮点数、字符、字符串等。

数组常用于存储和处理大量数据,提供了便捷的方式来访问和操作这些数据。

2.2 定义数组的方法

方法一:一次赋值全部元素

 数组名=( value0 value1 value2 value3 ......

Shell编程之函数和数组 (超详细)_第8张图片

方法二:通过下标值定义每个元素

数组名=[0]=value [1]=value1 [2]=value2 ....#[0] [1] [2] 为下标值

Shell编程之函数和数组 (超详细)_第9张图片

方法三:先定义列表,再引用列表的值定义数组

列表名="value0 value1 value2 value3 ...... "

数组名=($列表名)

Shell编程之函数和数组 (超详细)_第10张图片

方法四:一次只赋值一个元素

数组名[0]="value1"

数组名[1]="value2"

数组名[2]="value3"

Shell编程之函数和数组 (超详细)_第11张图片

方法五: read -a 交互式

read -a 数组名
要输入的内容 #数组内容 

echo ${数组名[@]} #查看 

Shell编程之函数和数组 (超详细)_第12张图片

下标值和索引值表示相同的意思,即元素在数组中的位置
数组的下标值从0开始,逐个递增,用于唯一标识数组中的每个元素

2.3 普通数组和关联数组

2.3.1 普通数组

普通数组(Regular Array)

  • 使用连续的整数值作为索引,从0开始递增。
  • 声明时使用 declaredeclare -a 命令。
  • 元素之间的顺序是固定的,根据索引进行访问。
  • 示例:
    fruits=("apple" "banana" "cherry")
    echo ${fruits[0]}  # 输出: apple
    echo ${fruits[1]}  # 输出: banana
    

普通数组使用整数索引访问数组中的元素。

2.3.2 关联数组

关联数组(Associative Array)

  • 使用任意字符串作为键来访问和存储元素。
  • 声明时使用 declare -A 命令。
  • 元素之间的顺序是不固定的,通过键进行访问。
  • 示例:
    declare -A ages
    ages["Alice"]=25
    ages["Bob"]=30
    echo ${ages["Alice"]}  # 输出: 25
    echo ${ages["Bob"]}    # 输出: 30
    

关联数组使用字符串键来标识和存储元素。

2.4 引用数组的值

1)获取数组长度(数组中所有元素的个数)

a=(1 2 3 4 5) #定义数组

echo ${#a[*]}  #显示下标总个数
或者
echo ${#a[@]}  #显示下标总个数      

Shell编程之函数和数组 (超详细)_第13张图片

2)获取数组数据列表(所有元素的值)

a=(1 2 3 4 5) #定义数组

echo ${a[*]}
或者
echo ${a[@]}

Shell编程之函数和数组 (超详细)_第14张图片

3)查看数组内某一个元素的值

x=${a[2]}

Shell编程之函数和数组 (超详细)_第15张图片

4)读取下标/索引的个数

a=(1 2 3 4 5) #定义数组
echo ${!a[*]} 

Shell编程之函数和数组 (超详细)_第16张图片

2.5 数组相关操作

2.5.1 数组遍历

数组遍历是指按顺序访问数组中的每个元素。

#举个例子#

#!/bin/bash
a=(1 2 3 4 5)
for i in ${a[@]}
do
echo $i
done

Shell编程之函数和数组 (超详细)_第17张图片

2.5.2 数组切片

数组切片是指从一个数组中提取出指定范围的元素

#基本格式

${ARRAY[@]:offset:number}
offset #要跳过的元素个数
number #要取出的元素个数

{ARRAY[@]:offset}  #取偏移量之后的所有元素 
#举个例子

a=({1..10}) #定义数组
echo ${a[@]:3:4} #跳过前三个 取后四个

Shell编程之函数和数组 (超详细)_第18张图片

2.5.3 数组删除

#删除数组中所有元素

#举个例子
a=(1 2 3 4 5)
unset a	
echo ${a[*]}

Shell编程之函数和数组 (超详细)_第19张图片

#删除指定元素
#举个例子
a=(1 2 3 4 5)
unset a[2]			
echo ${a[*]}

Shell编程之函数和数组 (超详细)_第20张图片

2.5.4 数组替换

a=(1 2 3 4 5)

echo ${a[@]/4/66} 	#${数组名[@或*]/查找字符/替换字符}
echo ${a[@]}			#并不会替换数组原有内容

a=(${a[@]/4/66})	#要实现改变原有数组,可通过重新赋值实现
echo ${a[@]}

2.6 数据排序算法之冒泡排序

2.6.1 概述

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

基本思想
冒泡排序的基本思想是对比相邻的两个元素值,如果满足条件就交换元素值,即交换元素的位置。

算法思路
冒泡算法由双层循环实现。

外部循环用于控制排序轮数,循环次数一般为要排序的数组长度减1次
因为最后一次循环只剩下一个数组元素,不需要对比,同时数组已经完成排序了。

内部循环主要用于对比数组中每个相邻元素的大小,以确定是否交换位置,对比和交换次数随排序轮数而减少。

2.6.2 应用实例之升序排序

#!/bin/bash
a=(90 20 30 40 50)
#  0   1  2  3   4    下标
l=${#a[@]}
for ((i=1;i<$l;i++))
do
        for ((j=0;j<$l-1;j++))
        do
        first=${a[$j]}
        k=$[$j+1]
        second=${a[$k]}

        if [ $first -gt $second ]
        then
        temp=$first
        a[$j]=$second
        a[$k]=$temp
        fi
        done
done

echo ${a[@]}

Shell编程之函数和数组 (超详细)_第21张图片

2.7 数组练习

2.7.1 提取最大值

#!/bin/bash
a=( 20 30 60 100 )

max=${a[0]}
l=${#a[*]}

for ((i=0;i<$l;i++))
do
if [[ $max -lt ${a[$i+1]} ]]
then
max=${a[$i+1]}
fi
done
echo $max

Shell编程之函数和数组 (超详细)_第22张图片

2.7.2 自定义数组,提取最小值

#!/bin/bash
read -p "请输入多个正整数(用空格隔开):" num
a=($num)

min=${a[0]}
l=${#a[*]}

for ((i=0;i<$l-1;i++))
do
if [[ $min -ge ${a[$i+1]} ]]
then
min=${a[$i+1]}
fi
done
echo $min

在这里插入图片描述

2.7.3 点名脚本

#点名脚本

#!/bin/bash
a=( aa bb cc dd ee ff )
x=${#a[@]}
j=`echo $[RANDOM%$x]`
n=$[ j+1 ]
echo "学号是 $n"
echo ${a[$j]}

Shell编程之函数和数组 (超详细)_第23张图片

你可能感兴趣的:(Shell编程,linux,运维,bash)