Bootstrap

函数和数组

1 函数

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
#查看指定函数的函数名
1.2.3 调用函数

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

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

#调用函数
function_name
1.2.4 传递参数

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

test() {
    echo "Parameter 1: $1"
    echo "Parameter 2: $2"
}
test $1 $2 
1.2.5 函数的返回值

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

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

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

返回值的作用:

  1. 对函数执行的结果进行判断和处理:函数可以返回不同的值来表示不同的执行状态或错误情况。
  2. 传递函数执行的结果给其他部分:函数的返回值可以被赋值给变量,能将函数的计算结果传递给其他命令或者再次使用。
  3. 作为脚本的退出状态码:根据不同的返回值来设置不同的退出状态码。
1.2.6 删除函数
unset function_name 
#从当前的 Shell 环境中删除指定的函数

1.3 函数的作用范围

函数在Shell脚本中仅在当前Shell环境中有效,脚本中的变量默认全局有效。
使用local命令可以将变量限定在函数内部使用。

1.4 函数文件

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

1.5 递归函数

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

1.5.1 函数练习:用递归函数计算正整数的阶乘
#!/bin/bash
# 定义递归函数
fact() {
  if (( $1 = 1 )); then
    echo 1
  else
    local temp=$(fact $(( $1 - 1 )))
    echo $(( $1 * $temp ))
  fi
}

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

2 数组

2.1 数组概述

就是定义了一系列,可以是整数,字符串,浮点的数的变量值的集合。数组可以一次性定义多个变量值,可以直接从数组当中引用

2.2 数组定义的方法

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

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

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

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

下标值和索引值表示相同的意思,即元素在数组中的位置。
数组的下标值从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 数组的切片

test1=(2 3 5 6 7 8)
echo ${test1[*]}
2 3 5 6 7 8
echo ${test1[*]:0:2}		# “0”表示索引位,“2”表示步长,包含其本身
2 3
echo ${#test1[*]}
6			#显示数组元素个数

2.5 数组的值如何进行替换

2.5.1 临时替换
test1=(2 4 6 8 9)
echo ${test1[*]}
2 4 6 8 9
echo ${test1[*]/4/66}
#临时替换
2 66 6 8 9
echo ${test1[*]}
2 4 6 8 9
2.5.2 永久替换
test1=(2 4 6 8 9)
echo ${test1[*]}
2 4 6 8 9
test1=(${test1[*]/4/66})
#永久替换
echo ${test1[*]}
2 66 6 8 9

2.6 删除数组

#删除数组,删除整个数组以及删除数组中的值
unset test1
echo ${test1[*]}
			# 数组值为空
test1=(2 4 6 8 10)
unset test1[1]
echo ${test1[*]}
2 6 8 10
echo ${test1[1]}
			# 结果为空值,只是删除该位的值,而不是删除该位
echo ${test1[2]}
6			# 6的索引依然是2,不会往前递补

2.7 追加数组中的元素

2.7.1 按照索引逐个添加
test1=(1 2 3 4)
echo ${test1[*]}
1 2 3 4
test1[4]=5
echo ${test1[*]}
1 2 3 4 5
test1[6]=5
echo ${test1[*]}
1 2 3 4 5 5
echo ${test1[5]}
			# 该方法不推荐使用,一是因为需要知道数组元素的个数,二是无法自动补齐
2.7.2 自动补齐添加
test1=(1 2 3 4 5)
test1+=(6 7)
echo ${test1[*]}
1 2 3 4 5 6 7
echo ${test1[5]}
6			#自动补齐
echo ${test1[6]}
7

2.8 向函数内的数组传参

test1 () {

  abc=($(echo $@))
  echo ${abc[*]}

}
abc1=(1 2 3 4 5)
test1 ${abc1[*]}

2.9 例题

2.9.1 例题1:把数组内的每个值*2,然后打印出新的数组
test1 () {
    abc=($(echo $@))
    for ((i=0;i<${#abc[*]};i++))
    do
        abc[$i]=$((${abc[$i]}*2))
    done
    echo ${abc[*]}
}
abc1=(1 2 3 4 5)
test1 ${abc1[*]}

或者

test1 () {
  abc=($(echo $@))
  for i in ${abc[*]} 
  do
    i=$(($i*2))
    a+=($i)
  done
  echo ${a[*]}
} 
abc1=(1 2 3 4 5)
test1 ${abc1[*]}
2.9.2 例题2:冒泡排序

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

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

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

#把数组内的元素(整数),按照从小到大,或者从大到小的顺序进行排列
abc=(20 10 60 40 50 30)
#循环几次
#位置如何交换
len=${#abc[*]}
for ((i=1;i<$len;i++))
do
    for ((k=0;k<$len-i;k++))
    do
#小的在左边,大的去右边
    first=${abc[$k]}
    j=$(($k+1))
    second=${abc[$j]}
    if [ "$first" -gt "$second" ]
    then
        temp=$first
        abc[$k]=$second
        abc[$j]=$temp
    fi
done
done
2.9.3 例题3:提取最大值
#!/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
2.9.4 例题4:点名脚本
#!/bin/bash
a=( aa bb cc dd ee ff )
x=${#a[@]}
j=`echo $[RANDOM%$x]`
n=$[ j+1 ]
echo "学号是 $n"
echo ${a[$j]}
;