数组定义、排序、shell脚本调试
一、数组定义方法
方法一:
数组名=(value0 value1 value2 ...)
方法二:
数组名=([0]=value [1]=value [2]=value ...)
方法三:
列表名="value0 value1value2 ...."
数组名=($列表名)
方法四:
数组名[0]="value"
数组名[1]="value"
数组名[2]="value"
查看 echo ${数组名[*]}
1.1 数组包括的数据类型
1、数值类型
2、字符类型:使用" "或’ '定义
1.2 获取数组长度
arr_number=(1 2 3 4 5)
arr_length=${#arr_number[*]}
${#arr_number [@]}
echo $arr_length
1.3 读取某下标赋值
arr_index2=${arr_number[2]}
echo $arr_index2
1.4 数组遍历
#!/bin/bash
arr_number=(1 2 3 4 5)
for v in ${arr_number[@]} in默认以空格为分割
do
echo $v
done
1.5 数组切片
arr=(1 2 3 4 5)
echo ${arr[@]} 输出整个数组
echo ${arr[@]:0:2} 获取${数组名[@或*]:起始位置:长度}的值
echo ${arr[@]:2:3}
1.6 数组替换
arr=(1 2 3 4 5)
echo ${arr[@]/4/66} $(数组名[@或*]/查找字符/替换字符)
echo ${arr[@]} 不会替换数组原有内容
arr=(${arr[@]/4/66}) 要实现改变原有数组,可通过重新赋值实现
echo ${arr[@]} 相当于创造了一个新的数组
1.7 数组删除
arr=(1 2 3 4 5)
unset arr #删除数组
echo ${arr[*]}
arr=(12345)
unset arr [2] #删除第三个元素
echo ${arr[*]}
1.8 数组追加元素
方法一:
array_name [index]=value
方法二:
array_name[${#array_name [@]}]=value
方法三:
array_name=("${array_name[@]}" value1... valueN)
双引号不能省略,否则,当数组array_name中存在包含空格的元素时会按空格将元素拆分成多个
不能将"@"替换为"*",如果替换为"*",不加双引号时与"@"的表现一致,加双引号时,会将数组array_name中的所有元素作为一个元素添加到数组中
方法四:
array_name+=(value1 ... valueN)
待添加元素必须用"()"包围起来,并且多个元素用空格分隔
1.9 向函数传数组参数
如果将数组变量作为函数参数,函数只会取数组变量的第一个值
#!/bin/bash
#这是错误的做法
test1 () {
echo "接收到的参数列表: $@"
newarrary=$1
echo "新数组的值为: ${newarrary[*]}"
}
array=(3 2 1 4 5)
echo "原始数组的值为: $(array[*]}"
test1 $array
解决这个问题则需要将数组变量的值分解成单个的值,然后将这些值作为函数参数使用。在函数内部,再将所有的参数重新组合成一个新的数组变量。
test2 () {
newarrary= ($(echo $@))
echo "新数组的值为:${newarrary [*]}"
}
array=(3 2 1 4 5)
echo "原始数组的值为: ${array[*]}"
test2 ${array[*]}
1.10 从函数返回数组
test2 () {
newarrary= (`echo $@`) 将数组传入函数,$@表示将每个元素分开输出"3" "2" "1" "4" "5"
sum=0
for value in ${newarrary[*]} for循环来求新数组newarray的和,,in可以以空格分隔数组中的元素进行提取
do
sum=$[$sum + $value] 求元素之和
done
echo $sum 输出元素之和即result1
}
test3 () {
newarrary = (`echo $@`) 将数组传入函数,$@表示将每个元素分开输出"3" "2" "1" "4" "5"
for ((i=0; i<=$[$# - 1]; i++)) $#表示新数组元素的总个数(5),因为这边的i同时也表示数组的索引号,所以要减1,即[0][1][2][3][4]
{
newarrary[$i]=$[${newarrary[$i]} * 2] 表示将新数组的每个元素*2形成新的元素值,即将数组中的每个元素都扩大两倍
}
echo ${newarrary[*]} 输出扩大两倍后的数组,即result2
}
array=(3 2 1 4 5)
echo "原始数组的值为: ${array[*])"
result1=`test2 ${array[*]}` 调用test2函数
echo "新数组的和为: $result1"
result2=(`test3 ${array[*]}`) 调用tset3函数
echo "新数组的值为: ${result2 [*]}"
二、数组排序算法
2.1 冒泡排序
类似气泡上涌的动作,会将数据在数组中从小到大或者从大到小不断的向前移动。
2.1.1 基本思想
冒泡排序的基本思想是对比相邻的两个元素值,如果满足条件就交换元素值,把较小的元素移动到数组前面,把大的元素移动到数组后面(也就是交换两个元素的位置) ,这样较小的元素就像气泡一样从底部上升到顶部。
2.1.2 算法思路
冒泡算法由双层循环实现,其中外部循环用于控制排序轮数,一般为要排序的数组长度减1次,因为最后一次循环只剩下一个数组元素,不需要对比,同时数组已经完成排序了。而内部循环主要用于对比数组中每个相邻元素的大小,以确定是否交换位置,对比和交换次数随排序轮数而减少。
#!/bin/bash
array= (63 4 24 1 3 15)
for ((i=1; i<${#array[*]}; i++)) #比较轮数为数组长度减1,从1开始
do
for ((j=0; j<${#array[*]}-i; j++)) #确定比较元素的位置,比较相邻两个元素,较大的数往后放,比较次数随比较轮数而减少
do
if [${#array[$j]} -gt ${array[$[$j+1]]} ] #如果第一个元素比第二个元素大就互换
then
temp=${array[$j]} ##把第一个元素值保存到临时变量中
array [$j]=${array [$[$j+1]]} ##把第二个元素值保存到第一个元素中
array[$[$j+1]]=$temp #把临时变量(也就是第一个元素原值)保存到第二个元素中
fi
done
done
echo $(array [*]}
2.2 直接选择排序
与冒泡排序相比,直接选择排序的交换次数更少,所以速度会快些。
2.2.1 基本思想
将指定排序位置与其它数组元素分别对比,如果满足条件就交换元素值,注意这里区别冒泡排序,不是交换相邻元素,而是把满足条件的元素与指定的排序位置交换(如从最后一个元素开始排序) ,这样排序好的位置逐渐扩大,最后整个数组都成为已排序好的格式。
#!/bin/bash
array=(63 4 24 1 3 15)
length=${#array[*]}
for ((i=1; i<$length; i++))
do
index=0
for ((j=1; j<=$length-i; j++))
do
if [${array[$j]} -gt ${array[$index]} ];then
index=$j
fi
done
temp=${array[$length-$i]}
array[$length-$i]=${array[$index]}
array[$index]=$temp
done
echo ${array[*]}
abc=(20 10 60 40 50 30)
echo "原数组的排列顺序为${abc[*]}"
length=${#abc[*]}
#定义排序轮数
for ((i=1; i<$length; i++ ))
do
index=0
#确定用于比较的第一个元素的索引范围
for ((k=1; k<=$length-i; k++))
do
first=${abc[$k]}
#通过比较获取最大元素的索引位置
if [ $first -gt ${abc[$index]} ];then
index=$k
fi
done
#获取最后一个元素的索引
last=$[$length-$i]
#把当前轮次的最后一个元素的值保存在临时变量中
temp=${abc[$last]}
#temp=${abc[$[$length-$i]]}
#把最大的元素的值赋给最后一个元素
abc[$last]=${abc[$index]}
#abc[$[$length-$i]]=${abc[$index]}
#把原最后一个元素的值赋给原最大值的位置的元素
abc[$index]=$temp
done
#输出排序后的数组
echo "排序后数组的排列顺序为${abc[*]}"
2.3 反转排序
以相反的顺序把原有数组的内容重新排序。
2.3.1 基本思想
把数组最后一个元素与第一个元素替换,倒数第二个元素与第二个元素替换,以此类推,直到把所有数组元素反转替换。
#!/bin/bash
array=(10 20 30 40 50 60)
length=${#array [*]}
for ((i=0; i<$length/2; i++))
do
temp=${array [$i]}
array [$i]=${array[$lenqth-$i-1]}
array [$length-$i-1]=$temp
done
echo ${array[*]}
三、Shell 脚本调试
sh [-nvx] 脚本名
-n:不会执行该脚本,仅查询脚本语法是否有问题,如果没有语法问题就不显示任
何内容,如果有问题会提示报错。
-v:在执行脚本时,先将脚本的内容输出到屏幕上然后执行脚本,如果有错误,也
会给出错误提示。
-x:将执行的脚本内容输出到屏幕上,这个是对调试很有用的参数。
当脚本文件较长时,可以使用 set 命令指定调试一段脚本。
#!/bin/bash
set -x //开启调试模式
read -p "请输入您的分数(0-100):" GRADE
if [ $GRADE -ge 85 ] && [ $GRADE -le 100 ]
then
echo "$GRADE 分!优秀"
set +x //关闭调试模式
elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ]
then
echo "$GRADE 分,合格"
else
echo "$GRADE 分?不合格"
fi
四、练习
将数组传入函数进行冒泡正序、倒序排序
#!/bin/bash
db1 () {
abc123=($(echo $@))
length1=${#abc123[*]}
for ((i=1;i<$length1;i++))
do
for ((j=0;j<$[ $length1 - $i ];j++))
do
if [ ${abc123[$j]} -gt ${abc123[$j+1]} ]
then
temp=${abc123[$[$j + 1]]}
abc123[$[$j + 1]]=${abc123[$j]}
abc123[$j]=$temp
fi
done
done
echo ${abc123[*]}
}
db2 () {
abc123=($(echo $@))
length2=${#abc123[*]}
for ((i=1;i<$length2;i++))
do
for ((j=0;j<$[ $length2 - $i ];j++))
do
if [ ${abc123[$j]} -lt ${abc123[$j+1]} ]
then
temp=${abc123[$[$j + 1]]}
abc123[$[$j + 1]]=${abc123[$j]}
abc123[$j]=$temp
fi
done
done
echo ${abc123[*]}
}
abc=(63 4 15 23 28 6 58)
echo "原数组为:${abc[*]}"
result1=`db1 ${abc[*]}`
echo "新的数组值为:${result1[*]}"
result2=`db2 ${abc[*]}`
echo "新的数组值为:${result2[*]}"