shell数组与排序
数组的概述
数组就是各种数据类型的元素按一定顺序排列的集合。把有限个元素变量或数组用一个名字命名,然后用编号区分他们的变量的集合。这个名字成为数组名,编号成为数组下标。组成数组的各个变量成为数组的分量,也称为数组的元素,有时也称为下标变量。
10 20 30 40 50 60 数组元素
0 1 2 3 4 5 数组下标
注意,数组的下标是从0开始的!
数组的定义方法
方法一:
数组名=(value0 value1 value2 . . . )
方法二:
数组名=([0]=value [1]=value [2]=value …)
方法三:
列表名=“value0 value1 value2”
数组名=($列表名)
方法四:
数组名[0]=“value”
数组名[1]=“value”
数组名[2]="value "
数组包括的数据类型
●数值类型
●字符类型:使用" "
或' '
定义
获取数组长度
arr—_number=(1 2 3 4 5)
arr_length=${#arr_number[*]}
${#arr_number[@]}
echo $arr_length
使用"*"
和"@"
都可以
获取数据列表
echo ${arr_number[*]}
echo ${arr_number[@]}
注意,这里不能直接$arr1,你直接 $ 跟数组名只会显示第一个元素
读取某下标赋值
arr_index2=${arr_number[2]}
echo $arr_index2
也可以根据下标查询对应元素的值
上面可以看到我arr2数组我没有下标2的元素,所以这里查看下标2为空,但是获取列表值它是连续显示的,所以有时不要被误导。
数组遍历
#!/bin/bash
arr_number=(1 2 3 4 5)
for V in ${arr_number[@]}
do
echo $v
done
数组切片
arr=(1 2 3 4 5)
echo ${arr[@]} #输出整个数组
echo ${arr[@]:0:2} #获取${数组名[@或*]:起始位置:长度}的值
echo ${arr[*]:2:3}
这里需要注意的是下标是从0开始的,选择获取哪个部分注意好下标,然后输入截取长度
数组替换
arr=(1 2 3 4 5)
echo ${arr[@]/4/66} #${数组名[@或*]/查找字符/替换字符}
echo ${arr[@]} #并不会替换数组原有内容.
arr=(${arr[@]/4/66}) #要实现改变原有数组,可通过重新赋值实现
echo ${arr[@]}
只事在元素中替换你输入需要替换的数字,并不是按照下标来替换,想要替换一个元素,需要匹配元素值来替换
我们再次获取数组可以看到并没有被替换,这只是临时替换,并不会替换数组原来的内容
想要改变替换原来的数组,需要重新赋值。注意,格式很重要,( )
别忘了
数组删除
arr=(1 2 3 4 5)
unset arr #删除数组
echo ${arr[*]}
arr=(1 2 3 4 5)
unset arr[2] #删除第三个元素
echo ${arr[*]}
可以看到,数组已被删除
或者还有可以指定元素进行删除,可以看到,40这个元素已经被删除了
数组追加元素
方法一:
array_ name [ index]=value
方法二:
array_ name[${#array_name [@]}]=value
是通过查看元素长度追加元素
方法三:
array_ name=("${array_ name[@]}" value1 ... valueN)
双引号不能省略,否则,当数组array_ name中存在包含空格的元素时会按空格将元素拆分成多个
例如:我们这里追加一个duan mu
,这里看上去是两个元素,但其实是一个元素
我们去掉双引号在看看。
这里追加没加双引号,可以看到,我们原来追加的duan mu
这个元素被拆分成了2个元素,所以双引号不能省略。
不能将“@”
替换为“*”
,如果替换为“*"
,不加双引号时与“@”
的表现一致,加双引号时,会将数组array_ name中的所有元素作为一个元素添加到数组中
for i in "${array_ name[@]}"; do echo $i; done
可以看到没加引号的"*"
和"@"
一样效果会用空格把元素拆开
方法四:
array_ name+= (value1 ... valueN)
待添加元素必须用“( )”
包围起来,并且多个元素用空格分隔。这种方法也是添加元素最方便的
数组函数的传递
向函数传数组参数
如果将数组变量作为函数参数,函数只会取数组变量的第一个值。
test1 ( ) {
echo "接收到的参数列表: $@"
newarrary= ($1)
echo "新数组的值为:${newarrary[*]}"
}
array=(30 10 20 50 40)
echo "原始数组的值为: ${array[*]}"
test1 $array
解决这个问题则需要将数组变量的值分解成单个的值,然后将这些值作为函数参数使用。在函数内部,再将所有的参数重新组合成一个新的数组变量。
test2 ( ) {
newarrary=($ (echo $@))
echo "新数组的值为: $ {newarrary[*]}"
array=(3 2 1 4 5)
echo "原始数组的值为: ${array[*]}"
test2 ${array[*]}
1.先将数组拆分成列表 $ {arr[@]}
2.函数通过$@获取之前将数组拆分成的列表 $@
3.在函数中重新把列表定义成数组 newarr= ( $@0)
4.对新的数组进行进一步的处理,再echo输出
从函数中返回数组
数组排序算法:
冒泡排序
类似气泡上涌的动作,会将数据在数组中从小到大或者从大到小不断的向前移动。
基本思想:
冒泡排序的基本思想是对比相邻的两个元素值,如果满足条件就交换元素值,把较小的元素移动到数组前面,把大的元素移动到数组后面(也就是交换两个元素的位置),这样较小的元素就像气泡一样从底部上升到顶部。
算法思路:
冒泡算法由双层循环实现,其中外部循环用于控制排序轮数,一般为要排序的数组长度减1次,因为最后一次循环只剩下一个数组元素,不需要对比,同时数组已经完成排序了。而内部循环主要用于对比数组中每个相邻元素的大小,以确定是否交换位置,对比和交换次数随排序轮而减小
例如下图可直观:
命令操作
#! /bin/bash
array=(63 4 24 1 3 15)
echo "old_array: ${array[*]}"
length=${#array[*]}
#定义比较轮数,比较轮数为数组长度减1,从1开始
for ((i=1; i<$length; i++) )
do
#确定比较元素的位置,比较相邻两个元素,较大的数往后放,比较次数随比较轮数而减少
for ((j=0; j<$length-i; j++))
do
#定义第一个元素的值
first=${array[$j]}
#定义第二个元素的值
k=$[$j+1]
second=${array[$k]}
#如果第一个元素比第二个元素大就互换
if [ $first -gt $second ]
then
#把第一个元素值保存到临时变量中
temp=$first
#把第二个元素值赋给第一个元素
array[$j]=$second
#把临时变量(也就是第一个元素原值)赋给第二个元素
array[$k]=$temp
fi
done
done
直接选择排序
与冒泡排序相比,直接选择排序的交换次数更少,所以速度会快些。
基本思想:
将指定排序位置与其它数组元素分别对比,如果满足条件就交换元素值,注意这里区别冒泡排序,不是交换相邻元素,而是把满足条件的元素与指定的排序位置交换(如从最后–个元素开始排序),这样排序好的位置逐渐扩大,最后整个数组都成为已排序好的格式。
反转排序
以相反的顺序把原有数组的内容重新排序。
基本思想:
把数组最后一个元素与第一 个元素替换,倒数第二个元素与第二个元素替换,以此类推,直到把所有数组元素反转替换。