Shell编程之循环语句与函数

目录

前言

一、循环语句

1.1 for 循环语句

1.2 while 循环语句

1.3  循环控制语句

 1.3.1  continue

1.3.2  break 

 1.3.3  exit 

1.4   until  循环语句

 二、shell函数应用

2.1  shell 函数概述

2.2   调用函数的方法

2.3  函数的返回值

 2.4 函数的传参数 

 2.5  函数变量的作用范围

 2.6 函数的递归

 三、shell  数组

3.1 shell数组的定义

3.2  数组的分类

3.3 应用场景

3.4 数组的定义方式

3.5  数组的数据类型

3.6  读取数组和元素

3.7 元素切片 

3.8  元素替换

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

3.10 数组追加元素

3.11 冒泡排序

 四、shell  脚本调试

4.1  echo  命令

​ 4.2  bash  命令

4.3  set  命令

 五、总结


前言

在生产过程中,经常会遇到某项任务需要多次执行的情况,而每次执行时仅仅是处理的对象不一样,其他的命令相同。当面对各种列表重复任务时,使用简单的if 语句已经难以满足要求,而顺序编写全部代码更是显得异常的繁琐、困难重重。这就要需要循环语句,可以很好的解决类似的问题。

一、循环语句

1.1 for 循环语句

使用 for 循环语句时,需要指定一个变量及可能的取值列表,针对每个不同的取值重复执行相同的命令序列,直到变量值用完退出循环。在这里,“取值列表”称为 for 语句的执行条件,其中包括多个属性相同的对象,需要预先指定(如通讯录、IP 黑名单)。

用法:

读取不同的变量值,用来逐个执行同一组命令

for循环经常使用在已经知道要进行多少次循环的场景

格式:

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

for 语句的结构:

for 语句的执行流程:首先讲列表中的第一个取值赋给变量,并执行do......done 循环体中的命令序列;然后讲列表中的第二个取值赋给变量,并执行循环体中的命令序列·······;以此类推,直到列表中的所有取值用完,最后讲调至done语句,表示循环结束。

案例一:简单的for循环

或着   输出文字

 案列二:根据姓名列表可以批量创建用户并,设置密码

根据人事部门给出的员工名单的拼音列表,在Linux服务器中添加相应的用户账号,初始密码设置为123456。其中员工姓名列表的账号数量并不固定,而且除了要求账号是拼音外,无其他的要求。针对上述的要求,可先指定员工的姓名列表book.txt文件里面,然后编写一个脚本,从book.txt文件中读取各用户的名称,重复添加用户数量,设置密码。

先创建一个姓名列表

编辑脚本

 查看结果

 批量删除用户,只需要参操上面的脚本即可,将for 循环体创建用户,并设置值密码的命令改为删除用户的命令即可,如下图所示:

 验证结果

 我们的手机里的app程序都会有密码才会打开,而且输入的密码会有次数限制,超过这个次数就会锁定账号,学会循环语句,自己也可一编写意见简单的密码限制次数,如下所示:

 案例三:根据IP地址列表检查主机的状态

        根据公司各服务器的IP地址的列表文件,检查其中各主机的ping连通性,输出各主机是否启动,关闭。其中服务器的数量并不固定,各服务器的IP地址也五特殊规律。

先创建一个包含IP地址的列表文件

 设置权限,并测试

 验证结果

注:在上述的脚本代码中,do·····done循环体内使用了if  条件选择语句,一针对不同的IP地址的测试结果进行判断,并输出相应的提示信息。实际上,if 语句、for语句以及其他的各种shell 脚本语句,都是可以嵌套使用的。

案例四:在生活中,周末的时候我们都会去商场里玩玩的,在节日的时候商场会做一些抽奖活动,

我们也可以使用shell脚本编一个抽奖的代码。

编写脚本

 进行验证:

案列五:编写shell脚本做一个正方形的星星形状

 案列六:可以使用shell脚本编写一个九九乘法表

 或者设置正三角形的九九乘法表

1.2 while 循环语句

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

格式:

while   条件测试操作

do

命令序列

done

while 循环结构:

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

     使用while 循环语句时,有两个特殊的条件测试操作,即true(真)和 false (假)。使用true作为条件时,表式条件永远成立,循环体内的命令序列将无限执行下去,除非强制终止脚本(或通过exit 语句退出脚本);反之,若使用false 作为条件,则循环体将不会被执行。这两个特殊条件也可以用在 if 语句的条件测试中。

案例一:简单的while循环语句使用

 

 案例二:使用while循环语句进入死循环会产生%cpu用的过多,资源占用太多,会产生僵尸进程:

产生死循环的脚本

产生结果

解决方案:

再循环语句中加 break 跳出循环

查看结果

案例三:批量添加规律编号的用户

        在一些技术培训和学习领域,出于实验或测试的目的,需要批量添加用户账号,这些用户账号包含固定的前缀字串,并按照数字顺序依次进行编号账户的数量往往也是固定的,

查看结果

 也可以批量删除前缀一样的用户账号,只需要把创建的账号命令序列改为删除的命令序列

查看结果

 案例四:在一些娱乐节目中,经常有猜价格的游戏,要求参与者在最短的时间内猜出展示商品的价格,当所猜的价格高或低时,主持人会给出相应的提示。我们也可以以此为原型,编写一个猜价格的shell  脚本。

 查看运行结果

 案例五:实时监控本机内存和硬盘剩余空间,剩余内存小于500M、根分区剩余空间小于1000M 时,发送报警邮件给 root 管理员。

#!/bin/bash
#提取根分区剩余空间
disk_size=$(df / |awk '/\//{print $4}')
#提取内存剩余空间
mem_size=$(free |awk '/Mem/{print $4}') 
while :
do
#注意内存和磁盘提取的空间大小都是以Kb 为单位
if [ $disk_size ‐le 512000 -a $mem_size ‐le 1024000 ];then 
mail ‐s Warning root <<EOF
Insufficient resources,资源不足EOF
fi 
done

案例六:我们在逛商场的时候,通常会进入好几家服装店买衣服,也可以根据我们进了几家店,买了几件衣服写个脚本,做个买东西的总价格

1.3  循环控制语句

for循环一般会搭配条件判断语句和流程控制语句一起执行,那么就会出现需要跳过循环和中止循环的情况,控制循环的命令有以下3个。

 1.3.1  continue

终止每次循环中的命令,但是不会完成终止命令

案例一:continue 

案例二:continue  2

1.3.2  break 

打断,马上停止本次循环,执行循环体外的代码。

案例一:break

案例二: break    2    

 区别:

continue 语句和 break 语句的区别是,continue 语句只结束本次循环,而不是终止整个循环。break 语句则是结束整个循环过程,不再判断执行循环的条件是否成立,并执行当前循环之后的语句。而且,continue 只能在循环语句中使用,即只能在 for、while 和 do…while 中使用,除此之外 continue 不能在任何语句中使用。

 1.3.3  exit 

直接跳出程序,后面可跟状态返回码如exit 1等等。

案例一:

1.4   until  循环语句

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

格式:

until  条件测试操作

do

       命令序列

done

until 语句的结构

 案例一:1-50,所有的数相加求和

 案例二:登录某个用户 使用root 发消息给某个用户。

 二、shell函数应用

Shell 函数也是我们经常使用的,因为有一些命令序列是需要反复调用执行的,若每次使用同一命令就重复写一遍,就会导致代码量很大,行数特别多。为解决该问题可以将命令序列按格式写在一起,以便可以重复使用。

2.1  shell 函数概述

将命令序列按格式写在一起

可方便重复使用命令序列

 shell 函数定义

2.2   调用函数的方法

方法一:

[function]    函数名  {

命令序列

[return  x ]

}

方法二:

函数名   () {

命令序列

[return  x ]

}

shell 函数定义的基本格式:[function] 是可选的,表示该函数的功能,这个是可以省略的;函数名后面加一个(),里面是没有内容的;而我们执行的命令序列放在{}里面的,[return  x ] 的作用是当命令序列执行完毕后返回给系统一个值,该项也是可以省略的。若有时我们调用的函数很多,那么我们也可以一次写好几个。

案例一:求两个数的和

 查看结果

案例二:使用函数来设置本地yum源的启动方式

验证结果

 注:函数名必须放在模块的下面

2.3  函数的返回值

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

函数一结束就取返回值,因为$?变量只返回执行的最后一条命令的退出状态码

 退出状态码必须是0~255,超出时值将为除以256取余

在函数体中用echo输出,并在函数体外使用变量赋值后,可再进一步对函数的返回值操作

案例:  求一个数乘2的值 ,使用$?把值返回出来

案例二:使用return 返回值也可判断目录下面的一个文件是目录还是普通文件

 验证:

 2.4 函数的传参数 

在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数…即使用位置参数来实现参数传递。

参数的用法:

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

参数的表示方法:

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

案例:简单的求两个数的和

 2.5  函数变量的作用范围

函数在shell脚本中仅在当前shell环境中有效

shell脚本中变量默认全局有效

将变量限定在函数内部使用local命令

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

案例一:使用local命令时,将变量限定在函数内部使用

 案例二:注释掉local 命令,函数默认为全局变量

 2.6 函数的递归

调用自己本身的函数

案例:使用递归计算阶乘

 三、shell  数组

3.1 shell数组的定义

 数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组)

数组元素的下标由 0 开始。

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

在shell语句中,使用、遍历数组的时候,数组格式要写成 ${arr[@]} 或 ${arr[*]}

3.2  数组的分类

普通数组:不需要声明直接定义,下标索引只能是整数

关联数组:需要用declare -A声明否则系统不识别,索引可以是字符串

3.3 应用场景

获取数组长度

获取元素长度

遍历元素

元素切片

元素替换

元素删除

3.4 数组的定义方式

            (10   20   30   40    50    60)

下标索引   0     1     2     3      4       5

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

数组名=(value1 value2 valuen3...)

${#a[*]}    :   显示字符串的长度

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

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

方法四: 可以把命令的结果用小括号括起来添加到数组,那么数组会以空格或者制表符区分每一个元素

3.5  数组的数据类型

 数值类型

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

"a b c d"                #字符串

"a" "b" "c" "d"        #列表

("a" "b" "c" "d")      #数组

3.6  读取数组和元素

3.7 元素切片 

3.8  元素替换

定义或替换某一个元素

${数组名[0]/旧字符/新字符}         

#会替换所有元素上能匹配到的字符,但是这是临时替换不会影响原有数组,可通过重新赋值实现替换原有数组

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

 unset数组名[n]                                     #删除某一个元素
unset数组名[*]或unset数组名[@]           #删除整个数组

案例:

3.10 数组追加元素

 数组名+=(变量1 变量2 ...)

使用下标追加元素:数组名【下标】=变量

 数组名[数组长度]=元素值

 

3.11 冒泡排序

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

基本思想:

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

算法思路:

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

扩展:数组元素遍历

 输出1-20以内的偶数

 四、shell  脚本调试

在 Shell 脚本开发中,经常碰到一些规范方面的问题,例如忘了使用引号或在 if 语句末尾处忘记加 fi 结束。要注意把复杂的脚本简单化,要思路清晰,并且分段实现。当执行脚本时出现错误后,不要只看那些提示的错误行,而是要观察整个相关的代码段。
为避免编写的脚本出错,除了在编写脚本时注意书写规范,排除语法错误,更重要的是 利用调试脚本工具来调试脚本。echo 命令是最有用的调试脚本工具之一,一般在可能出现问题的脚本中加入 echo 命令,采用的是分段排查的方式。

4.1  echo  命令

选项:

-e  表示输出反斜杠转义符

-n 表示不换行输出

\n 输出换行

\t 横向制表符

\b 表示退格不显示前一个字符

\c 抑制更多的输出或不换行

案例:

 4.2  bash  命令

命令语法: sh [-nvx]  脚本名

■常用参数的具体含义为:
-n:不会执行该脚本,仅查询脚本语法是否有问题,如果没有语法问题就不显示任 何内容,如果有问题会提示报错。
-v:在执行脚本时,先将脚本的内容输出到屏幕上然后执行脚本,如果有错误,也 会给出错误提示。
-x:将执行的脚本内容输出到屏幕上,这个是对调试很有用的参数。

4.3  set  命令

set   -x   开启调试模式

set   +x   关闭调试模式

案例:

 案例二:

 五、总结

1.for 循环语句可根据已知的列表对象重复执行命令序列,更适合无规律的循环操作

2.while 循环语句可根据特定的条件重复执行命令序列,更适合有规律的循环操作

3.until 循环语句与while 语句相反,在生产上基本不常用

4.在Linux系统中有很多服务启动脚本定义了丰富的shell函数,并嵌套了各种语句

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值