3.信你能理解的!shell脚本之循环语句与函数,数组,冒泡排序

循环语句

一,for循环语句结构

  • 在实际工作中,经常会遇到某项任务需要多次执行的情况,而每次执行时仅仅是处理的 对象不一样,其他命令相同

  • 例如,根据通讯录中的姓名列表创建系统账号,根据服务器清 单检查各主机的存活状态,根据 IP 地址黑名单设置拒绝访问的防火墙策略等

  • 当面对各种列表重复任务时,使用简单的 if 语句已经难以满足要求,而顺序编写全部代码更是显得异常烦琐、困难重重。而在不同场景使用不同的循环语句,可以很好地解决类似的问题

for语句的结构

  • 读取不同的变量值,用来逐个执行同一组命令,
  • for分别有,列表循环,不带列表循环,类C风格的for循环

1.1格式:

for 变量名 in 取值列表
do
	命令序列
done

image-20220628122054627

1.2例:

列表循环:
列表循环:
1.例:
#!/bin/bash
a=3                    	//定义变量
for i in `seq $a`      //seq可以引用变量
do
    echo $i
done
[root@localhost opt]# sh 1.sh
1
2
3

2.例:
#!/bin/bash
for i in a b c       //i这里实际没有调用,所以就相当于in 后面几个参数就循环几次
do
  echo 123
done
[root@localhost opt]# sh 1.sh
123
123
123

3.例:
#!/bin/bash
for i in a b c     //这里用到i变量,所以就正常显示i的值 (a b c)  
do
  echo  $i
done
[root@localhost opt]# sh 1.sh
a
b
c

4.例:打印3次hello world,虽然定义了变量i,但没使用它,它只是控制了循环次数
#!/bin/bash
for i in {
    
    1..3}`seq 5` 或 对应的数字或字母(a b c,1 2 3do
  echo "hello world"
done

小结:

for 循环中 for i in {list} 使用方式

i为自定义变量名

in 首先将 in 之后的内容,定义为一个list 然后循环对列表中的元素进行取值,并每次取值后赋予给变量 i (自定义变量名)

{list} 列表:①定义循环次数 ②每个元素,在每次循环时都会被依次取出,然后复制给变量名

以 do 为分割

command :定义每次循环时,要输出的指令

done :结束

不带列表循环:
#!/bin/bash
for i
do
  echo "hello"
done 
[root@localhost opt]# sh 1.sh      //没有给脚本传参所以执行了没有结果
[root@localhost opt]# sh 1.sh a   //把a赋值给了i,i有了值它就开始执行do..done了
hello

第二种:
#!/bin/bash
for i
do
  echo "$i"       //把恒定显示改为,变量显示
done 
[root@localhost opt]# sh 1.sh 
[root@localhost opt]# sh 1.sh world
world
类C风格的for循环:
格式:
for ((expr1;expr2;expr3))
do
     command
done
expr1:定义变量并赋初值                                     i=1
expr2:决定是否循环(定义可取值的范围,目的是定义循环次数)      i<=3
expr3:决定循环变量如何改变,决定循环什么时候退出(自定义步长)  i++或i=+2

1.例:打印1-5
迭代
#!/bin/bash
for ((i=1;i<=3;i++))
do
  echo "$i"
done
[root@localhost opt] sh 1.sh 
1
2
3

2.例:打印1-10的奇数
#!/bin/bash
for ((i=1;i<=10;i+=2))
do
  echo "$i"
done
2.例:计算1-100奇数和
#!/bin/bash
sum=0
for ((i=1;i<=100;i+=2))
do
  let sum=$i+$sum
done
  echo "$sum"

二,while语句循环结构

  • while循环一般用于有条件判断的循环,若判断条件为真,则进入循环,当条件为假跳出循环
  • 简单说:重复测试某个条件,只要条件成立则反复执行

while的写法:
1.语法结构

2.死循环

2.1格式:

while 条件测试操作
do
	命令序列
done

image-20220628230629933

2.2例:

1.例:打印1-5
#!/bin/bash
i=1                          //定义变量i=1
while [ $i -le 5 ]           //当i等于5时停止循环
do    
  echo "$i"                  //每次循环输出i的值
  let i++                    //每次循环+1
done                        //循环到大于等于5时结束循环
 echo "最后i的值为: $i"     //输出最后$i的值
[root@localhost while]# sh 1.sh
1
2
3
4
5
最后i的值为: 6

2.例:上个条件基础上查看循环几次
#!/bin/bash
i=1
sum=0
while [ $i -le 5 ]
do
  echo "$i"
  let i+=2
  let sum++
 echo "最后i的值为$i,循环了$sum 次 "
done
[root@localhost while]# sh 1.sh
1
最后i的值为 3,循环了 13
最后i的值为 5,循环了 25
最后i的值为 7,循环了 3

2.2循环控制语句,退出循环

循环一般会搭配条件判断语句和流程控制语句一起执行,那么就会出现需要跳过循环中止循环的情况,有下面三种:

  • exit:退出了支持执行,当前脚本执行的进程,所以可以结束脚本,可以定义返回值来判断脚本哪里出错(直接跳出程序,后面可跟状态返回码,直接跳出程序所以不会执行最后的echo hi ,并返回码是100通过$?查看)

image-20220701135735507

  • break:结束当前脚本大循环,不会影响脚本下面写入的其他循环(打断,马上停止本次循环,执行循环体外的代码)

打印1-10的数字,7后面的都不打印

image-20220630121831648

  • continue:退出(当前)本次小循环(嵌套里面的),直到跳到下一次循环,如果条件成立还会继续循环(继续,但不会执行循环体内下面的代码了,开始重新开始下一次循环)

打印1-5的数字,3不打印,结果会是1245,3不输出,因为跳出后面的echo语句执行下一次循环了

image-20220630121059310

while true死循环

i=1                       ##定义变量        
while true [ $1 -eq 2 ]   ##使用了true 不管判断条件是否为真,都会循环执行
do
  echo "死循环"
 #  exit                  ##若加上循环到exit 直接退出当前循环
done

2.例猜数字,猜不对就一直猜
#!/bin/bash
num=10
while true
do
read -p "请输入数字:" zi
 if [ $zi -eq $num ];then
     echo "你猜对了"
     break 1                 ##表示猜对退出当前这个循环,不影响其他嵌套循环
elif [ $zi -gt $num ];then
     echo "你猜大了"
elif [ $zi -lt $num ];then
     echo "你猜小了"
fi
done
[root@c7-1 home]# vim while2.sh 

#!/bin/bash
i=1						//定义变量i=1
while [ $i -le 100 ]	//重复测试$1是否小于等于100,直至$i等于100
        do				//命令列表
        if [[ $i%3 -ne 0 ]]	//条件检测 $i取余3,是否不等于0
        then				//条件成立
                echo "$i"	//输出 $i的值
        fi					//结束判断
        let i++				//每次循环i+1
done						//结束循环

三,until循环语句

  • 跟while相反,条件为假进入循环,条件为真退出循环
  • 重复测试某个条件,只要条件不成立则反复执行

3.1格式:

until 条件测试操作
do
	命令序列
done

image-20220630112914905

3.2例:

[root@c7-1 home]# vim 50.sh 

#!/bin/bash
i=1				        //定义变量i=1
sum=0			
until [ $i -eq 51 ]		//$i等于51时停止执行
do	
        sum=$[$i+$sum]	//定义sum等于$i + $sum
        let i++			//每次循环i+1	

done
echo "$sum				//打印结果 $sum
[root@c7-1 home]# bash 50.sh 
1275
until死循环

image-20220630115409318

四,shell函数

  • 将命令序列按格式写在一起
  • 可方便重复使用命令序列

4.1格式:

#格式一:
[ function ] 函数名(){
    
    
	命令序列
	[return x]         //使用return或exit可以显示地结束函数	
}
##规范写法
#!/bin/bash
function dxj{
    
                      //定义调用函数名
 cat /opt/name.txt             //要调用的命令(参数)
}
dxj                           //调用函数名,使用里面的命令(参数)

[root@qjm ~]# sh 2.sh
1 zhangsan
2 lisi
3 wangwu


#格式二:
函数名 (){
    
    	           
命令序列
}

#!/bin/bash
dxj(){
    
    
 cat /opt/name.txt
}
dxj
##最常用,因为最简洁

image-20220701152319359

  • 函数定义完之后并不会自动执行,需要调用才行,好处在于可以写一段功能代码作为函数,有需要就直接调用定义的时候哪怕出现语法错误也没关系,不调用就不会报错
    当然我们写函数最终目的还是为了调用,为了实现某个功能块

4.2函数的调用

直接在脚本里定义函数的代码块后写函数名即可完成调用

#!/bin/bash
dxj(){
    
                        //定义了一个函数叫做dxj
 echo "this is a dxj"    //函数的功能是打印this is a dxj
}  
dxj                     //直接写函数名就会运行函数体内的代码
[root@qjm ~]# sh 2.sh
this is a dxj

注意1:函数名必须是唯一,如果先定义了一个,再用同样的名称定义,第二个会覆盖第一个的功能,出现了你不想要的结果,所以一定不要重名(函数名可以一致但要在不同环境执行才可以)

1例:

[root@qjm ~]# vim 2.sh
#!/bin/bash
xtz (){
    
    
 echo hello 
}
xtz (){
    
    
 echo world
}
xtz
[root@qjm ~]# sh 2.sh
world

注意2:调用函数之前必须先进行定义

2例:

#!/bin/bash
dxj (){
    
    
 echo hello
}

xtz (){
    
    
 echo world
}

he (){
    
    
 echo "$(dxj) $(xtz)"
}
he
[root@qjm ~]# sh 2.sh
hello world

注意3:不一定要在脚本开头就定义函数,只要调用之前定义的就可以

  • 如果是在其他地方嵌套调用等情况,不可以直接写函数值,避免无法识别,可以用反撇号引起来,相当于是调用函数的结果

3例:

#!/bin/bash
dxj (){
    
    
 echo hello
}

xtz (){
    
    
 echo world
}

he (){
    
    
 echo "`dxj` `xtz`"    //这里如果直接是dxj和xtz的话,打印出来的不会是hello world而会是dxj xtz
}
he
[root@qjm ~]# sh 2.sh
hello world

4例:部署本地yum源

[root@qjm ~]# vim yum.sh 

#!/bin/bash
backuprepo (){
    
    				//函数名
cd /etc/yum.repos.d			
mkdir repo,bak
mv *.repo repo.bak
mount /dev/sr0 /mnt &>/dev/null
}

makelocalrepo (){
    
    
echo
[local]
name=local
baseurl=file:///mnt
enable=1
gpgcheck=0 > local.repo
}

userlocalrepo (){
    
    
yum clean all > /dev/null
yum makecache > /dev/null
yum install -y httpd > /dev/null
}

backuprepo			//调用
makelocalrepo		//调用
userlocalrepo		//调用

4.3 函数返回值

return表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值
使用原则

  1. 函数一结束就取返回值,因为$?变量只返回执行的最后一条命令的退出状态码
  2. 退出状态码必须是0~255,超出时值将为256取余
#!/bin/bash
function test1 {
    
                 ##定义函数
 read -p "请输入一个数字" st   ##定义交互式变量
 return $[$st*2]             ##设置返回值乘2
}
test1                        ##调用函数
echo $?                      ##测试返回值

[root@qjm ~]# sh -x 2.sh     ##以下执行结果
+ test1
+ read -p 请输入一个数字 st
请输入一个数字2
+ return 4
+ echo 4
4

4.4函数传参

1.例:

##算出两个数求和
#!/bin/bash
sum (){
    
    
  read -p "请输入第一个数:" x     ##定义交互式变量
  read -p "请输入第二个数:" d
  echo  "你输入的两个数为: "$x $d  
   h=$((x + d))                  ##计算和
  echo "两个数的和为:$h"          ##输出和
}
sum                             ##调用函数里执行玩的集合

[root@qjm ~]# sh 3.sh
请输入第一个数:3
请输入第二个数:5
你输入的两个数为: 3 5
两个数的和为:8

2.例:调用函数时直接传递参数

##使用调用函数的方式计算位置变量的和
#!/bin/bash
dxz (){
    
    
 let sum=$1+$2    ##这里的位置变量是函数的位置变量,所以要写在调用函数的后面,如果是调用脚本时使用则不能成功
 echo $sum 
}
dxz 7 8

[root@qjm ~]# sh 1.sh
15

image-20220703164834391

3.例:通过脚本传递参数给函数中的位置参数

#!/bin/bash
dxz (){
    
    
 let sum=$1+$2
 echo $sum 
}
dxz $1 $2    ##这里相当于调用了脚本的参数了,然后把脚本的位置变量传递给函数进行计算

[root@qjm ~]# sh  1.sh 12 23
35

image-20220703165250380

  • 阶乘
##阶乘
#!/bin/bash
jiecheng (){
    
         ##定义一个函数名
cheng=1          ##再自定义变量
for i in {
    
    1..6}  ##使用for进行一道六的循环
do
let cheng=$i*$cheng  ##使用let计算(乘),for循环的值和自定义变量的值,就是下面图片的结果
done
echo $cheng
}
jiecheng

[root@qjm ~]# sh 1.sh
720

image-20220703171027848

##交互式阶乘
#!/bin/bash
jiecheng (){
    
    
cheng=1
read -p "请输入你想计算几的阶乘: " jie
for i in `seq $jie`
do
let cheng=$i*$cheng
done
echo $cheng
}
jiecheng

image-20220703172553630

4.5函数的作用范围

  • 在 Shell 脚本中函数的执行并不会开启一个新的子Shell,而是仅在当前定义的Shell 环境中有效
  • 如果Shell脚本中的变量没有经过特殊设定,默认在整个脚本中都是有效的
  • 在编写脚本时,有时需要将变量的值限定在函数内部,可以通过内置命令local来实现
  • 函数内部变量的使用,可以避免函数内外同时出现同名变量对脚本结果的影响
  • shell脚本中变量默认全局有效
  • local命令:将变量限定在函数内部使用
#!/bin/bash
dxz (){
    
     
 local i      ##将变量限定在函数内部使用,就不会影响函数外相同的变量名
i=8           
echo $i       ##输出的是函数里的变量
}
i=9
dxz
echo $i       ##输出的是函数外的变量
[root@qjm ~]# sh 1.sh
8
9

image-20220703162213673

#上述脚本中dxz函数内部使用了local命令设置变量 i,其作用是将变量 i 限定在函数内部
#dxz函数外部同样定义了变量 i,内部变量 i 和全局变量 i 互不影响
#脚本执行时先调用了函数dxz,函数内部变量 i 为8,所以输出结果是8
#调用完函数之后,给变量 i 赋值为9,再打印外部变量i,所以又输出9

  • 本地变量与全局变量

在脚本里定义的变量或者在函数体没有声明为本地变量的都为全局变量,意思是在当前shell环境都识别

如果需要这个变量只在函数使用则可以在函数中用local关键字声明,这样即使函数体外有个重名的变量也没关系,不影响在函数体的使用

如果使用 source 执行脚本的话就能看出差别

[root@qjm ~]# a=nihao
#!/bin/bash
f2 (){
    
    
 echo $a
 a=world
 echo $a    ##先打印a的值,然后改变a的值再打印
}
f2
[root@qjm ~]# sh 6.sh    

world

[root@qjm ~]# source 6.sh    ##刷新了变量后,第一个a的值改变了
nihao
world

##使用local把变量固定在函数内
[root@qjm ~]# a=nihao
#!/bin/bash
f2 (){
    
    
 echo $a
local a=world    ##不会受环境变量影响
 echo $a    
}
f2
[root@qjm ~]# source 6.sh    
world
world

image-20220703181249972

1.例:将算数字总和和算奇数和偶数和的脚本融合在一个脚本中并用函数根据用户的输入来调用他们

#!/bin/bash
##总和
SUM (){
    
    
 sum=0
 read -p "计算1到几的和:" num
 for ((i=1;i<=$num;i++))
 do
 let sum=$i+$sum
 done
 echo $sum
}

##奇数和
oushu (){
    
    
 sum=0
 read -p "计算1到几的奇数和:" num
  for ((i=1;i<=$num;i+=2))
 do
 let sum=$i+$sum
 done
 echo $sum
}

##偶数和
jishu (){
    
    
 sum=0
 read -p "计算0到几偶数和:" num
 for ((i=0;i<=$num;i+=2))
 do
 let sum=$i+$sum
 done
 echo $sum
}
if [ $1 == SUM ];then
SUM
elif [ $1 == oushu ];then
oushu
elif [ $1 == jishu ];then
jishu
else
   echo "参数错误"
fi

注:奇数偶数字母写反了,详细看别看错了

奇数和image-20220703190744032

偶数和image-20220703190806933

总和

4.6函数的递归

函数自己调用自己的本身

1.例:列出目录内文件列表,目录用蓝色表示,文件显示层级关系

#!/bin/bash
list(){
    
    
for i in $1/*                 ##循环查看位置变量下的所有,$i赋值$1下的所有内容
do
        if [ -d $i ];then      ##判断是否是目录,是加颜色,不是直接输出
        echo -e "\e[34m$i\e[0m"
        list $i " $2"          ##调用自己本身,再输出$i下的子目录或文件再循环判断,$2只是作为空格的存在,让文件显示层级关系
        else
        echo "$2$i"
fi
done
}
list $1 $2

image-20220703192909195

五,数组

5.1数组的定义

  • 数组是存放相同类型数据的集合,在内存中开辟了连续的空间,通常配合循环使用
  • 数组的类型

普通数组:不需要声明直接定义,下标索引只能是整数
关联数组:需要用declare -A 声明否则系统不识别,索引可以是字符串

5.2数组的定方式

A="1 2 3 456"       //定义字符串
A=(1 2 3 4 456)		//定义数组(里面的每个数字又被称为元素)
   0 1 2 3 4		//其下标示,0为起始(又称数组下标,索引下标)

第一种:

直接把要加入数组的元素用小括号括起来,中间用空格分开

数组名=(value0 value1 value2)

num=(11 22 33 44)
echo ${
    
    #num}     ##显示单个字符串长度
2
[root@qjm ~]#  echo ${num[*]}  ##显示详细字符串(数组)内容,#号换@也可以效果一样
11 22 33 44
[root@qjm ~]# echo ${#num[*]}    ##显示所有字符串(数组)长度,#号换@也可以效果一样
4
第二种:

精确的给每一个下标索引定义一个值加入数组,索引数字可以不连续

数组名=([0]=value [1]=value [2]value ...)

num=([0]=55 [1]=66 [2]77 [4]88)

[root@qjm ~]#  echo ${num[*]}
[0]55 [1]66 [2]77 [3]88
第三种:

先把要加入数组的元素全部先赋值给一个变量,然后引用这个变量加入到数组

列表名="value0 value1 value2...."
数组名=($列表名)

list="11 12 13 14"
num=($list)
[root@qjm ~]# echo ${num[*]}
11 12 13 14 
[root@qjm ~]# echo ${#num[*]}
4
第四种:

根据下标定义

数组名[0]="11"
数组名[0]="22"
数组名[0]="33"

数组名[0]="value"
数组名[0]="value"
数组名[0]="value"

5.3数组包括的数据类型

  • 数值类型

  • 字符类型:使用 " " 或 ’ ’ 定义

1.获取数组长度
num=(11 22 33 44)
[root@qjm ~]# echo ${#num[*]}    ##显示所有字符串(数组)长度,#号换@也可以效果一样
4
[root@qjm ~]# echo ${#num[@]}
4
2.获取数据列表
num=(11 22 33 44)
[root@qjm ~]#  echo ${num[*]}  ##显示详细字符串(数组)内容,#号换@也可以效果一样
11 22 33 44
[root@qjm ~]# echo ${#num[@]}
11 22 33 44
3.数组元素遍历
#!/bin/bsah
arr=(1 2 3 4 5)
for i in ${arr[*]}   
do
echo $i
done
[root@qjm ~]# sh 4.sh
1
2
3
4
5
4.元素切片
[root@qjm ~]# qjm=(4 7 9 5 2)  ##定义数组
[root@qjm ~]# echo ${qjm[*]}   ##输出数组里的元素
4 7 9 5 2
0 1 2 3 4    ##索引下标
[root@qjm ~]# echo ${qjm[*]:2:3}  ##提取从索引下标2开始的3个元素
9 5 2
[root@qjm ~]# echo ${qjm[*]:2:2}  ##提取从索引下标2开始的2个元素
9 5
[root@qjm ~]# echo ${qjm[*]:3:2}  ##提取从索引下标3开始的2个元素
5 2
[root@qjm ~]# echo ${qjm[*]:1:2}  ##提取从索引下标1开始的2个元素
7 9
5.数组元素替换
[root@qjm ~]# mqj=(36 35 34 33 32 31)  ##定义数组
[root@qjm ~]# echo ${mqj[*]}           ##输出数组里的元素
36 35 34 33 32 31
[root@qjm ~]# echo ${mqj[*]/3/55}      ##将有3的元素替换或增加一个指定的数值55,只是覆盖,不是永久替换(仅替换每个元素的第一个匹配项)
556 555 554 553 552 551

6.数组删除
[root@qjm ~]# jmq=(34 45 55 12)
[root@qjm ~]# echo ${jmq[*]}
34 45 55 12
[root@qjm ~]# unset jmq       ##删除数组
[root@qjm ~]# echo ${jmq[*]}

[root@qjm ~]# jmq=(34 45 55 12)
[root@qjm ~]# echo ${jmq[*]}
34 45 55 12
[root@qjm ~]# unset jmq[3]   ##删除第四元素,中括号里的是索引下标,删除后只是不显示元素而已,但会变为空格占用索引下标,如果查看长度的话会减少
[root@qjm ~]# echo ${jmq[*]}
34 45 55 

1.例:以数组的方式定义随机点名
[root@qjm opt]# vim w   ##创建编辑一个文件写入名字和对应编号
1大狮子
2小兔子
3小海豚
4花蝴蝶
5小家雀

[root@qjm opt]# vim w.sh  ##编写数组脚本
#!/bin/bash
bu=`cat /opt/w`        ##定义变量
arr=($bu)             ##定义数组变量
for i in ${arr[*]}    ##循环查看里的内容数组
do
a=$[$RANDOM%5]       ##定义变量取随机数
done
echo "小动物的编号和名字是: ${arr[$a]}"   ##输出随机数对应的编号和名字

[root@qjm opt]# sh w.sh
小动物的编号和名字是: 1大狮子

简单方法
#!/bin/bash
bu=`cat /opt/w`
arr=($bu)
a=$[$RANDOM%5]
echo "小动物的编号和名字是: ${arr[$a]}"

六,数组排序算法(冒泡排序)

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

  • 基本思想

冒泡排序的基本思想是对比相邻的两个元素值,如果满足条件就交换元素值,把较小的元素移动到数组前面,把较大的元素移动到数组后面(也就是交换两个元素的位置),这样较小的元素就像气泡一样从底部上升到顶部

  • 算法思路

冒泡算法由两层循环实现,其中外部循环用于控制排序轮数,一般为要排序的数组长度减1次,因为最后一次循环只剩下一个数组元素,不需要对比,同时数组就已经完成排序了

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

  • 例:希望a和b的值对调位置
a=10
b=20

dxz=$a     ##增加自定义变量dxz的目的,是为了让a自定义变量的赋值空闲出来,后续好调换
a=$b
b=$dxz

##dxz=$a
dxz=10
a=10
b=20

##a=$b
dxz=10
a=20
b=20

##b=$a
dxz=10
a=20
b=10

a=20
b=10
##冒泡排序元素调换
dxz=(10 20)
echo ${dxz[*]}

##交换位置
xtz=`echo ${
     
     dxz[0]}`

dxz[0]=`echo ${
     
     dxz[1]}`

dxz[1]=$xtz

echo ${dxz[*]}

[root@qjm ~]# sh 7.sh
10 20
20 10

变量
for i in KaTeX parse error: Expected 'EOF', got '#' at position 13: {arr[*]} #̲#循环查看里的内容数组 do …[$RANDOM%5] ##定义变量取随机数
done
echo “小动物的编号和名字是: KaTeX parse error: Expected '}', got 'EOF' at end of input: {arr[a]}” ##输出随机数对应的编号和名字

[root@qjm opt]# sh w.sh
小动物的编号和名字是: 1大狮子

简单方法
#!/bin/bash
bu=cat /opt/w
arr=( b u ) a = bu) a= bu)a=[$RANDOM%5]
echo “小动物的编号和名字是: KaTeX parse error: Expected '}', got 'EOF' at end of input: {arr[a]}”


# 六,数组排序算法(冒泡排序)

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

- 基本思想

冒泡排序的基本思想是对比相邻的两个元素值,如果满足条件就交换元素值,把较小的元素移动到数组前面,把较大的元素移动到数组后面(也就是交换两个元素的位置),这样较小的元素就像气泡一样从底部上升到顶部

- 算法思路

冒泡算法由两层循环实现,其中外部循环用于控制排序轮数,一般为要排序的数组长度减1次,因为最后一次循环只剩下一个数组元素,不需要对比,同时数组就已经完成排序了

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

- 例:希望a和b的值对调位置

```bash
a=10
b=20

dxz=$a     ##增加自定义变量dxz的目的,是为了让a自定义变量的赋值空闲出来,后续好调换
a=$b
b=$dxz

##dxz=$a
dxz=10
a=10
b=20

##a=$b
dxz=10
a=20
b=20

##b=$a
dxz=10
a=20
b=10

a=20
b=10
##冒泡排序元素调换
dxz=(10 20)
echo ${dxz[*]}

##交换位置
xtz=`echo ${
     
     dxz[0]}`

dxz[0]=`echo ${
     
     dxz[1]}`

dxz[1]=$xtz

echo ${dxz[*]}

[root@qjm ~]# sh 7.sh
10 20
20 10

image-20220704105208080

猜你喜欢

转载自blog.csdn.net/weixin_61269220/article/details/125726890