自动化运维必须要学的Shell脚本之——数组(冒泡排序和反转排序等)

Posted 码海小虾米_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自动化运维必须要学的Shell脚本之——数组(冒泡排序和反转排序等)相关的知识,希望对你有一定的参考价值。

一、数组的基本操作

1.1 什么是数组

  • 数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小(与 php 类似)。

  • 与大部分编程语言类似,数组元素的下标由 0 开始。

  • Shell 数组用括号来表示,元素用"空格"符号分割开

1.2 数组的语法格式

  • 格式一:
数组名=(value1 value2 ... valuen)
arr_number=(1 2 3 4 5 6 7 8 9)
  • 格式二:
数组名=([0]=value0 [1]=value0 [2]=value0 ...)
arr_number=([0]=1 [1]=2 [2]=3 [3]=4)
  • 格式三:
列表名:“value1 value2 valueN ..."
数组名=($列表名)
list_number="1 2 3 4 5 6"
arr_number=($list_number)
  • 格式四:
数组名[0]="value"
数组名[1]="value"
数组名[2]="value"
arr_number[0]=1
arr_number[1]=2
arr_number[2]=3

1.3 数组的数据类型

  • 数值类型
  • 字符类型
  • 使用 “ ”(双引号) 或者 ‘ ’ (单引号)定义

1.4 获取数组的长度

在这里插入图片描述

arr_length=${#arr_number[@]}
		   ${#arr_number[*]}
echo $arr_length 

在这里插入图片描述

1.5 获取数组的列表

echo ${arr_number[*]}
echo ${arr_number[@]}

在这里插入图片描述

1.6 获取数组下标对应的值

arr_number=(1 2 3 4 5 6 7 8 9 0)
arrindex3=${arr_number[3]}
echo $arrindex3 

在这里插入图片描述

1.7 遍历数组

arr_number=(0 1 2 3 4 5 6 7 8 9)

for i in ${arr_number[@]}
do
    echo $i
done

在这里插入图片描述

1.8 数组切片

arr_number=(0 1 2 3 4 5 6 7 8 9)

echo "输出整个数组: " ${arr_number[@]}
echo "取出数组1到3: " ${arr_number[@]:1:3}
echo "取出数组5到9: " ${arr_number[@]:5:5}
echo "取出数组0后面所有: " ${arr_number[@]:0}

在这里插入图片描述

1.9 数组替换

echo " ${arr[@]/4/666} :这种写法会输出替换后的数组,但是是临时的,并未改变原数组
arr=(${arr[@]/4/666}) :使用重新赋值,可以修改原数组

arr=(0 1 2 3 4 5 6 7 8)
echo "初始的数组为: " ${arr[@]}
echo "输出替换的数组:" ${arr[@]/4/666}		
echo "替换后查看原数组为: " ${arr[@]}

arr=(${arr[@]/4/666})
echo "替换后的数组为: " ${arr[@]}

在这里插入图片描述

1.10 数组删除和指定下标的值删除

在这里插入图片描述

1.11 数组追加元素

  • 方法一 :直接使用下标进行元素的追加
array_name[index]=value

在这里插入图片描述

  • 方法二:将数组的长度作为下标进行追加元素(比如下面例子,原数组的长度为5,数组内最后一个元素的下标为4,所以使用5意思也是追加,跟方法一道理一样)
array_name[${array_name[@]}]=value

在这里插入图片描述

  • 方法三:

双引号不能省略,否则,当数组array name中存在包含空格的元素时会按空格将元素拆分成多个
不能将“@”替换为 “ * ”,如果替换为“ * ”,不加双引号时与"@"的表现一致,加双引号时,会将数组array name中的所有元素作为一个元素添加到数组中。

array_name=("${array_name[@]}" value1 ...valueN)

在这里插入图片描述
使用循环测试 加不加双引号的情况下,使用@和 * 的区别
在这里插入图片描述

  • 方法四:使用+=进行追加

待添加元素必须用“()”包围起来,并且多个元素用空格隔开

array_name+=(value1...valueN)

在这里插入图片描述

二、将数组作为函数的参数

2.1 将数组传入函数返回新的数组

1.如果将数组作为函数的参数,函数只会取数组变量的第一个值,如下:
在这里插入图片描述
2.解决上述的问题:需要将数组变量的值分解成单个的值,然后将这些值作为函数参数使用,在函数内部,再将所有的参数重新组合成一个新的数组变量。
在这里插入图片描述

2.2 将数组传入函数进行计算返回结果

在这里插入图片描述
结果:
在这里插入图片描述

二、数组的排序(冒泡/直接选择/反向)

2.1 冒泡排序

1.概述:类似气泡上涌的动作,会将数据在数组中从小到大或者从大到小不断向前移动。
2.基本思想:冒泡排序的基本思想是对比相邻的两个元素值,如果满足条件就交换元素值,把较小的元素移动到数组前面,把大的元素移动到数组后面(也就是交换两个元素的位置),这样较小的元素就像气泡一 样从底部上升到顶部。
3.算法思路:冒泡算法由双层循环实现,其中外部循环用于控制排序轮数,一般为要排序的数组长度减1次,因为最后一次循环只剩下一个数组元素,不需要对比,同时数组已经完成排序了。而内部循环主要用于对比数组中每个相邻元素的大小,以确定是否交换位置,对比和交换次数随排序轮数而减少

# 定义一个数组,内容无序
array_num=(77 20 67 4 35 88 55)
# 输出未排序之前的数组,方便和后面做对比
echo "没有进行排序之前的数组: " ${array_num[*]} 
# 定义一个变量,代表数组的长度
arr_length=${#array_num[*]}
# 外循环作用将数组进行循环,次数为数组的长度-1
for ((i=1;i<$arr_length;i++)){
    # 内循环为数组内相邻两个元素的对比
    for ((j=0;j<$arr_length-i;j++)){
    # 将数组的第一个元素赋予给变量first
    first=${array_num[$j]}
    # 将数组的第二个元素赋予给变量second
    second=${array_num[$[$j+1]]}
        # 进行判断,如果第一个数大于第二个数
        if [ $first -gt $second ]
        then
            # 使用临时变量接收第一个数
            temp=$first
            # 然后将第二个数给第一个数,因为第一个数大,需要换位
            array_num[$j]=$second
            # 最后再将临时变量的值赋给第一个数
            array_num[$[$j]+1]=$temp
        fi
    }
}
echo "从小到大排序后的数组为:  ${array_num[*]}"

在这里插入图片描述
结果:
在这里插入图片描述

2.1 直接选择排序

1.概述:与冒泡排序相比,直接选择排序的交换次数更少,所以速度会快些。
2.基本思想:将指定排序位置与其它数组元素分别对比,如果满足条件就交换元素值,注意这里区别冒泡排序,不是交换相邻元素,而是把满足条件的元素与指定的排序位置交换(如从最后一 个元素开始排序),这样排序好的位置逐渐扩大,最后整个数组都成为已排序好的格式。

  6 # 定义数组,无顺序即可
  7 array=(44 22 55 91 4 6 42 100 333 12)
  8 echo "没排序的数组为: ${array[*]}" 
  9 # 将数组的长度赋予变量lg
 10 lg=${#array[*]}
 11 # 确定循环比较的次数
 12 for ((i=1;i<$lg;i++)){
 13     # 定义变量index为0,作为数组的下标
 14     index=0
 15     # 使用循环进行比较,每轮比较的次数为lg-i
 16     for ((j=0;j<$lg-i;j++)){
 17         #对比获取最大值元素的索引位置,如果当前数比index0大
 18         if [ ${array[$j]} -gt ${array[$index]} ];then
 19              # 就把该元素对应的下标索引给index
 20              index=$j
 21         fi
 22     }
 23     # 定义最后每轮最后元素的下标为last
 24     last=$[$lg-$i]
 25     # 定义临时变量用来接受最后的元素的值
 26     temp=${array[$last]}
 27     # 将下标索引为index的数给当前数组的最后一个元素
 28     array[$last]=${array[$index]}
 29     # 将之前临时变量temp的值给下标为index的元素,实现对换
 30     array[$index]=$temp
 31 }
 32 echo "排序后的数组为: ${array[*]}"

在这里插入图片描述
结果:
在这里插入图片描述

2.1 反转排序

1.概述:以相反的顺序把原有数组的内容重新排序。
2.基本思想:把数组最后一个元素与第一个元素替换,倒数第二个元素与第二个元素替换,以此类推,直到把所有数组元素反转替换。

  6 # 定义数组随便,我这里按顺序方便对比
  7 array=(a b c d e f g)
  8 echo "反转之前的数组为: " ${array[*]}
  9 
 10 # 取出数组的长度
 11 lg=${#array[*]}
 12 # 使用循环,次数为长度的一般即可,因为反转是相互的
 13 for ((i=0;i<lg/2;i++)){
 14     # 每次反转的时候定义一个临时变量用来接受此次反转的第一个变量
 15     temp=${array[$i]}
 16     # 将此次反转操作时的最后一个变量赋予给此次反转的第一个
 17     array[$i]=${array[$lg-$i-1]}
 18     # 然后将临时变量接收的值赋予给此次反转的最后一个
 19     array[$lg-$i-1]=$temp
 20 }
 21 echo "反转之后的数组为: " ${array[*]}

在这里插入图片描述
结果:
在这里插入图片描述

以上是关于自动化运维必须要学的Shell脚本之——数组(冒泡排序和反转排序等)的主要内容,如果未能解决你的问题,请参考以下文章

自动化运维必须要学的Shell脚本之——编程规范和变量详细解读

自动化运维必须要学的Shell脚本之——函数的使用

自动化运维必须要学的Shell脚本之——免交互操作,分分钟解放双手!

自动化运维必须要学的Shell脚本之——正则表达式的详解

自动化运维必须要学的Shell脚本之——条件语句的详细解读

自动化运维必须要学的Shell脚本之——循环语句(forwhile和until循环)