目录
一、循环语句
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 跳出循环
查看结果
案例三:批量添加规律编号的用户
在一些技术培训和学习领域,出于实验或测试的目的,需要批量添加用户账号,这些用户账号包含固定的前缀字串,并按照数字顺序依次进行编号账户的数量往往也是固定的,
查看结果
也可以批量删除前缀一样的用户账号,只需要把创建的账号命令序列改为删除的命令序列
查看结果
1.3 循环控制语句
for循环一般会搭配条件判断语句和流程控制语句一起执行,那么就会出现需要跳过循环和中止循环的情况,控制循环的命令有以下3个。
1.3.1 continue
终止每次循环中的命令,但是不会完成终止命令
案例一:continue
1.3.2 break
打断,马上停止本次循环,执行循环体外的代码。
案例一:break
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,所有的数相加求和
二、shell函数应用
Shell 函数也是我们经常使用的,因为有一些命令序列是需要反复调用执行的,若每次使用同一命令就重复写一遍,就会导致代码量很大,行数特别多。为解决该问题可以将命令序列按格式写在一起,以便可以重复使用。
2.1 shell 函数概述
将命令序列按格式写在一起
可方便重复使用命令序列
shell 函数定义
2.2 调用函数的方法
方法一:
[function] 函数名 {
命令序列
[return x ]
}
方法二:
函数名 () {
命令序列
[return x ]
}
shell 函数定义的基本格式:[function] 是可选的,表示该函数的功能,这个是可以省略的;函数名后面加一个(),里面是没有内容的;而我们执行的命令序列放在{}里面的,[return x ] 的作用是当命令序列执行完毕后返回给系统一个值,该项也是可以省略的。若有时我们调用的函数很多,那么我们也可以一次写好几个。
案例一:求两个数的和
查看结果
注:函数名必须放在模块的下面
2.3 函数的返回值
return表示退出函数并返回一个退出值,脚本中可以用 $ ? 变量显示该值
使用原则:
函数一结束就取返回值,因为$?变量只返回执行的最后一条命令的退出状态码
退出状态码必须是0~255,超出时值将为除以256取余
在函数体中用echo输出,并在函数体外使用变量赋值后,可再进一步对函数的返回值操作
案例: 求一个数乘2的值 ,使用$?把值返回出来
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.2bash 命令
命令语法: sh [-nvx] 脚本名
■常用参数的具体含义为:
-n:不会执行该脚本,仅查询脚本语法是否有问题,如果没有语法问题就不显示任 何内容,如果有问题会提示报错。
-v:在执行脚本时,先将脚本的内容输出到屏幕上然后执行脚本,如果有错误,也 会给出错误提示。
-x:将执行的脚本内容输出到屏幕上,这个是对调试很有用的参数。
4.3 set 命令
set -x 开启调试模式
set +x 关闭调试模式
五、总结
1.for 循环语句可根据已知的列表对象重复执行命令序列,更适合无规律的循环操作
2.while 循环语句可根据特定的条件重复执行命令序列,更适合有规律的循环操作
3.until 循环语句与while 语句相反,在生产上基本不常用
4.在Linux系统中有很多服务启动脚本定义了丰富的shell函数,并嵌套了各种语句