Shell编程之循环语句与函数

引言

Shell作为一种脚本编程语言,包含循环、分支等其他程序控制结构,从而能够轻松完成更加复杂的工作。本文主要讲了for、while语句的具体用法。

一、循环语句

1、for循环语句

使用 for 循环语句时,需要指定一个变量及可能的取值列表,针对每一个不同的取值重复执行相同的命令序列,直到变量值用完退出循环。

for 循环语句的语法结构如下:

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

在这里插入图片描述
for 语句的执行流程

  • 首先将列表中的第1个取值赋给变量,并执行 do···done 循环体中的命令序列
  • 然后将列表中的第2个取值赋给变量,并执行循环体中的命令序列……
  • 以此类推,直到列表中的所有取值用完,最后将跳至 done 语句,表示结束循环

在这里插入图片描述
在这里插入图片描述

1.1 计算整数和

用户随机输入一个小于100的整数,并计算从1到该数之间所有整数的和
在这里插入图片描述
在这里插入图片描述

1.2 列出奇偶数

在这里插入图片描述
在这里插入图片描述

1.3 批量添加、删除用户

添加用户
在这里插入图片描述
调用这个文件,根据这个文件来创建用户名
在这里插入图片描述
创建用户成功
在这里插入图片描述
删除用户

在这里插入图片描述
在这里插入图片描述

1.4 根据IP地址列表检查主机状态

在这里插入图片描述
调用ip.txt
在这里插入图片描述
查看主机状态
在这里插入图片描述

1.5 密码验证

在这里插入图片描述
在这里插入图片描述

1.6 随机抽奖

在这里插入图片描述
在这里插入图片描述

1.7 九九乘法表

在这里插入图片描述
在这里插入图片描述

2、while语句

for循环语句非常适用于列表对象无规律,且列表来源已固定(如某个列表文件)的场合。而对于要求控制循环次数、操作对象按数字顺序编号、按特定条件执行重复操作等情况,则更适合使用另一种循环—while语句。

  • 使用 while循环语句时,可以根据特定的条件反复执行一个命令序列,直到该条件不再满足时为止。但是在脚本应用中,应该避免出现死循环的情况,否则后边的命令操作将无法执行。
  • 循环体内的命令序列中应包括修改测试条件的语句,以便在适当的时候使测试条件不再成立,从而结束循环。

while循环语句的语法结构如下所示:

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

在这里插入图片描述
执行流程:

  • 首先判断 while 后的条件测试操作结果,如果条件成立,则执行 do···done 循环体中的命令序列
  • 返回 while 后再次判断条件测试结果,如果条件仍然成立,则继续执行循环体
  • 再次返回到 while 后,判断条件测试结果…如此循环
  • 直到 while 后的条件测试结果不再成立为止,最后跳转到 done 语句,表示结束循环

2.1 列出1-100之间能被3整除的数

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

把-ge换成-ne就是不等于
在这里插入图片描述

在这里插入图片描述

2.2 猜数字

[root@zhang home]# vim text2.sh 

#!/bin/bash
cnum=520
while true
do
read -p "请输入数字:" num
    if [ $num -eq $cnum ]
    then
        echo "你猜对了"
        break
    elif [ $num -gt $cnum ]
    then
        echo "你猜大了"
    elif [ $num -lt $cnum ]
    then
        echo "你猜小了"
    fi
done

在这里插入图片描述
在这里插入图片描述

2.3 猜商品价格

[root@zhang while]# vim pricegame.sh 

#!/bin/bash
PRICE=$(expr $RANDOM % 1000)
a=0
echo "商品实际价格范围为0-999,猜猜看是多少?"
while true
do
read -p "请输入你猜测的价格数目:" INT
let a++

if [ $INT -eq $PRICE ]
     then
     echo "恭喜你答对了,实际价格是 $PRICE"
     echo "你总共猜测了 $a 次"
     exit 0
elif [ $INT -gt $PRICE ]
then
     echo "你猜高了!"
else
     echo "你猜低了!"
fi
done

在这里插入图片描述

在这里插入图片描述

2.4 商场购物

#!/bin/bash
i=1
sum=0

while [ $i -le 3 ]
do
   echo "进入第$i家商店"
   read -p "是否进入看看(yes/no)" doing
   while [ $doing = "yes" ]
    do
       echo "1:衣服 ¥200"     
       echo "2:鞋子 ¥999"
       echo "3:帽子 ¥120"
       echo "4:裤子 ¥279"
       read -p "请选择你需要购买的商品的序列号:" num

       case $num in
       1)
         echo "衣服购买成功"
         expr $[sum+=200] &>/dev/null
       ;;


       2)
         echo "鞋子购买成功"
         expr $[sum+=999] &>/dev/null
       ;;
       3)
         echo "帽子购买成功"
         expr $[sum+=120] &>/dev/null
       ;;
       *)
         echo "裤子购买成功"
         expr $[sum+=279] &>/dev/null

       esac
            read -p "是否进行购买(yes/no)?" doing
       done
       let i++
       if [ $doing = "no" ]
       then continue
       fi
done
echo "购物总价为:$sum"

在这里插入图片描述
在这里插入图片描述

3、until语句

重复测试某个条件,只要条件不成立则反复执行

语法结构如下所示:

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

在这里插入图片描述

3.1 计算1~50的和值

[root@zhang until]# vim 50.sh

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

done
echo "$sum                       //打印结果 $sum

在这里插入图片描述

二、Shell函数

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

1、函数基本格式

[function] 函数名(){
  命令序列
[return x]                           #使用return或exit可以显示的结束函数 
}


或者

                                     #也可以省略掉[function],它表示该函数的功能

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

2、函数返回值

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

  • 函数一结束就取返回值,因为$?变量只返回执行的最后一条命令的退出状态码
  • 退出状态码必须是0~255,超出时值将为256取余

返回值范围

[root@zhang hanshu]#vim retun.sh 
#!/bin/bash
function test1 {
read -p "请输入数字:" num
return $[num*2]
}
test1
echo $?

[root@zhang hanshu]#sh retun.sh 
请输入数字:3
6
[root@zhang hanshu]#sh retun.sh 
请输入数字:127
254
[root@zhang hanshu]#sh retun.sh 
请输入数字:128
0

在这里插入图片描述
在这里插入图片描述

3、函数应用示例

3.1 简单函数调用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.2 调用函数安装本地yum源

在这里插入图片描述

4、函数的作用范围

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

local一般用于局部变量声明,多在在函数内部使用。

  1. shell脚本中定义的变量是global的,其作用域从被定义的地方开始,到shell结束或被显示删除的地方为止。
  2. shell函数定义的变量默认是global的,其作用域从“函数被调用时执行变量定义的地方”开始,到shell结束或被显示删除处为止。函数定义的变量可以被显示定义成local的,其作用域局限于函数内。但请注意,函数的参数是local的。
  3. 如果同名,Shell函数定义的local变量会屏蔽脚本定义的global变量。

举例:
在这里插入图片描述
在这里插入图片描述

5、函数的参数

参数的用法

函数名称 参数1 参数2 参数3...

参数的表示方法

$1 $2 $3 ......${10} ${11}......

5.1 传参计算两个数的和

在这里插入图片描述

5.2 调用函数删除文件

在这里插入图片描述

5.3 用return返回值

在这里插入图片描述
在这里插入图片描述

6、递归函数

调用自己本身的函数

6.1 递归遍历目录

在这里插入图片描述
运行结果
在这里插入图片描述

6.2 阶乘

**plan 1:**计算特定数的阶乘
在这里插入图片描述
在这里插入图片描述

**plan 2:**以递归方式计算随机数的阶乘
在这里插入图片描述
在这里插入图片描述

三、Shell数组

1、定义数组

可以在单行中使用数值列表来定义一个数组

array_var=(test1 test2 test3 test4)
#这些值将会存储在以0为起始索引的连续位置上
或者
#将数组定义为一组“索引—值”
array_var[0]="test1"
array_var[1]="test2"
array_var[2]="test3"
array_var[3]="test4"

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

num=([0]=55 [1]=66 [2]=77 [4]=88)
数组名=([0]=value [1]=value [2]=value. . .)

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

list="11 12 13 14"
num=($list)

2、获取数组长度

${#arr}显示字符串长度
在这里插入图片描述
以列表形式打印出数组中的所有值
在数组中,@和*的效果一样
在这里插入图片描述
数组元素的遍历
在这里插入图片描述

3、元素切片

[root@zhang ~]# arrr=(10 20 30 40 50)
[root@zhang ~]# echo ${arr[*]}
10 20 30 40 50
[root@zhang ~]# echo ${arr[*]:2:3}      #提取出第2个数后面的3个值
30 40 50
[root@zhang ~]# echo ${arr[*]:1:3}       #提取出第1个数后面的3个值
20 30 40
[root@zhang ~]# echo ${arr[*]:0:4}         #提取出第0个数后面的4个值
10 20 30 40

在这里插入图片描述

4、元素替换

[root@zhang ~]# arr=(1 3 5 7 9)
[root@zhang ~]# echo ${arr[*]}
1 3 5 7 9
[root@zhang ~]# echo ${arr[*]/3/88}     #3指的是查找数组里面的字符,88指的是需要替换的字符
1 88 5 7 9
[root@zhang ~]# echo ${arr[*]/9/100}
1 3 5 7 100

在这里插入图片描述

5、元素删除

[root@zhang ~]# arr=(2 4 6 8 10)
[root@zhang ~]# echo ${arr[*]}
2 4 6 8 10
[root@zhang ~]# unset arr[2]   #删除下标为2的值,即索引为2的值
[root@zhang ~]# echo ${arr[*]}
2 4 8 10
[root@zhang ~]# unset arr[4]
[root@zhang ~]# echo ${arr[*]}
2 4 8

在这里插入图片描述

6、冒泡排序

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

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

算法思路:
冒泡算法由双层循环实现,其中外部循环用于控制排序轮数,一般为要排序的数组长度减1次,因为最后一次循环只剩下一个数组元素,不需要对比,同时数组已经完成排序了。而内部循环主要用于对比数组中每个相邻元素的大小,以确定是否交换位置,对比和交换次数随排序轮数而减少。

score=(77 13 91 56 88)

两两对比,第1个和第2个比,小的值到前面,大的值到后面。
以此类推。第2个和第3个比,第3个和第4个比,第4个和第5个比

------------第一轮------------
77 13 91 56 88 第一次对比 数组长度-1 第一轮比较往后值, 最大值为91 
13 77 91 56 88 第二次对比 
13 77 91 56 88 第三次对比 
13 77 56 91 88 第四次对比 
13 77 56 88 91
------------第二轮------------
13 77 56 88 91 第一次对比 数组长度-1第二轮比较往后,第二大的数字88 
13 77 56 88 91 第二次对比 
13 56 77 88 91 第三次对比 
13 56 77 88 91
------------第三轮-----------
13 56 77 88 91 第一次对比 数组长度-1第三轮比较往后,第三大的数字77 
13 56 77 88 91 第二次对比 
13 56 77 88 91
------------第四轮-----------
13 56 77 88 91 第一次对比 数组长度-1第四轮比较往后,第四大的数字56 
13 56 77 88 91

举例:

#!/bin/bash
array=(98 76 24 100 35 3)
echo "old_array:${array[*]}"
lt=${#array[*]}
#定义比较轮数,比较轮数为数组长度-1,从1开始
for ((i=1;i<$lt;i++))
do
  #确定比较元素的位置,比较相邻两个元素,较大的数往后放,比较次数随比较轮数而
减少
  for ((j=0;j<$lt-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
echo "new_array:${array[@]}"

在这里插入图片描述
在这里插入图片描述

四、总结

本文主要讲了三种循环语句和Shell函数的定义方法以及数组的使用方法。

  • for语句可根据已知的列表对象重复执行命令序列,更适合无规律的循环操作。
  • while语句可根据特定的条件重复执行命令序列,更适合有规律的循环操作。
  • until语句重复测试某个条件,只要条件不成立则反复执行。
  • Shell函数的调用
  • Shell数组的使用方法
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风雪一更ing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值