1、函数的作用
函数的定义
function 函数名 {
command
}
或者----------------------
函数名 () {
command
函数定义完之后并不会自动执行,需要调用才行,好处在于可以写一段功能代码作为函数,有需要就直接调用。定义的时候哪怕出现语法错误也没关系,不调用就不会报错,当然我们写函数最终目的还是为了调用,为了实现某个功能块。
函数的返回值
return表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值
使用原则:
函数一结束就取返回值,因为$?变量值返回执行的最后一条命令的退出状态码
退出状态码必须0~255,超出时值将为取余256(例如:返回码为444,那么将444%256)
2、函数的调用
直接在脚本里定义函数的代码块写函数名即可完成调用
案例:简单的函数调用
注意:函数名必须是唯一的,如果先定义了一个,再用同样的名称定义第二个,那么第二个会覆盖第一个的功能,所以这里一定要注意不要重名!
案例:相同函数名的调用
注意:调用函数之前,必须先进行定义!就是说函数的调用必须在函数的后面。
案例:函数调用顺序问题
在其它函数中嵌套调用函数的情况,不可以直接写函数的值,便面无法识别,可以用反撇号引起来,相当于是调用函数的结果
1
案例:假如调用fun3放其中一个函数的前面
注意:不一定要在脚本开头就定义函数,只要调用之前定义就可以
案例:最后调用函数,将fun3函数放在其它两个函数中间
案例:使用脚本编写手动安装yum源,需要用到函数的调用
2、return的用法
终止一个函数
return命令允许带一个整形参数(0-255),这个整数将最为函数的“退出状态码”返回给调用这个函数的脚本,并且这个整数也被复制给变量$?
如果没有return命令,函数将返回最后一个指令的退出状态
案例:对比函数中添加与不添加return的区别
不加return
加return
案例2:测试文件是否存在
3、 函数的作用范围
在shell脚本中函数的执行并不会开启一个新的子shell,而是仅在当前定义的shell环境中有效,如果shell脚本中的变量没有经过特殊设定,默认在整个脚本中都是有效的。
在编写脚本时,有时需要将变量的值限定在函数内部,可以通过内置命令local来实现,函数内部变量的使用,可以避免函数内外同时出现同名变量对脚本结果的影响
shell脚本中变量默认全局有效
local命令:将变量限定在函数内部使用
上述脚本中fun1函数内部使用了local命令设置变量num,其作用是将变量num限定在函数内部,fun1函数外部同样定义了变量num,内部变量num和全局变量互不影响。脚本执行先调用了函数fun1,函数内部变量num为10,所以输出10,调完函数,变量num赋值为100,所以有输出100
4、函数的参数
在shell中,调用函数时可以向其传递参数,在函数体内部,通过$n的形式来获取参数值,例如,$1表示第一个参数,$2表示第二个参数,就是使用位置参数来实现参数传递。
5、函数的递归调用
函数自己调用自己
二、数组
数组是存放相同类型数据的集合,在内存中开辟了连续的空间,通常配合循环使用
1、数组的分类
普通数组: 不需要申明直接定义,下标索引只能是整数
关联数组: 需要用declare -A 申明,否则系统不识别,索引可以是字符串
2、数组的定义方式
2.1 第一种
直接把要加入数组的元素用小括号括起来,中间用空格分开
格式: 数组名=(value0 value 1 value2)
例如:num=(10 20 30 40)
2.2 第二种
精确的给每一个下表索引定义一个值加入数组,索引数字可以不连续
格式: 数组名=([0]=value [1]=value [2]=value....)
例如:num=([0]=10 [1]=20 [2]=30 [3]=40)
2.3 第三种
先把要加入数组的元素全部先复制给一个变量,然后引用这个变量加入到数组
格式: 数组=($列表名)
变量= "value0 value1 value2 value3"
例如:
list= "10 20 30 40"
num=($list)
2.4 第四种
根据下表定义
格式: 数组名[0]="value"
数组名[1]="value"
数组名[2]="value"
例如: num[0]="10"
num[1]="20"
num[2]="30"
3、获取数组的长度和元素
获取数组的所有元素的总数
获取数组所有元素的列表内容
根据下标获取数组元素的内容
根据下标获取元素的长度
总结
定义数组最简单的办法就是:num=(10 20 30 40)
读取数组中的全部长度使用:echo ${#num[*/@]}
读取数组中的下标对应的元素长度: echo ${#num[下标]}
读取数组中的全部内容使用:echo ${num[*/@]}
读取数组中的下标对应的元素内容: echo ${num[下标]}
4、数组的遍历
使用for循环。遍历输出数组中的每一个元素
5、数组元素的切片(提取)
就是将数组中的元素输出的时候,进行指定哪一块元素进行输出。依靠索引进行查找到元素的位置。
6、数组元素的替换
7、数组元素的删除
删除整个数组
删除数组中单个元素
9、冒泡排序
类似气泡上涌的动作,会将数据的数组从小到大或者从大到小不断的向前移动
基本思想
冒泡排序的基本思想就是对比相邻的两个元素值,如果满足在这里插入图片描述
条件就交换元素值,把较小的元素移动到数组前面,把大的元素移动到数组后面(就是交换两个元素的位置),这样较小的元素就像气泡一样从底部上升到顶部。
算法思路
冒泡算法有双层循环实现,其中外部循环用于控制排序轮数,一般为要排序的数组长度减1次,因为最后一次循环只剩下一个数组,不需要对比,同时数组已经完成排序了。而内部循环主要用于对比数组中每个相邻元素的大小,以确定是否交换位置,对比和交换次数随排序轮数而减少
案例:用冒泡排序对数组元素进行排序(最小数放前面)
注意:此方法是将第一个数和后面的每一个数进行比较,然后第一个数为最小的数,然后第二个数和后面的每一个数进行比较,然后第二个数为倒数第二小的数,依次比较,循环结束,即可完成排序。
案例2:用冒泡排序对数组元素进行排序(最大数放后面)
注意:第一个数个第二数进行比较,大的放第二个数的位置,第二个和第三个数进行比较,大的放第三个数的位置,直到最后一个数为最大数,然后又重新循环。直到循环结束,排序完成。
案例:实现用户输入数组中的元素,然后将数组内容进行降序排列
代码如下:
#!/bin/bash
#定义数组中的元素
i=0
while true
do
read -p "请输入数组中的元素(数字),截止输入stop:" ack
#用户输入的为stop,那就不再进行获取数组元素
if [ $ack = "stop" ];then
break
fi
#将用户输入的变量赋值到数组中
num[$i]=$ack
let i++
done
lh=${#num[*]}
echo "你输入的数组为:${num[*]},长度为:$lh"
#下面进行冒泡排序
for ((i=1;i<${#num[*]};i++))
do
for ((j=0;j<$lh-$i;j++))
do
first=${num[$j]}
b=$[j+1]
sec=${num[$b]}
if [ $first -lt $sec ];then
temp=$first
num[$j]=$sec
num[$b]=$temp
fi
done
done
echo "排序后的数组为:${num[*]}"
三、总结
函数
函数的作用: 就是实现一个功能块,然后进行调用,函数名不能重复
函数中可以使用return进行返回一个状态码 ,可以根据状态码查看函数的运行效果
函数中定义变量,可以 使用local关键字进行定义成局部变量 ,局部变量只能在函数中使用,不会与shell环境中的其它相同变量名冲突
函数的参数可以使用位置参数进行传参 ,在调用时可以直接输入位置参数的值。也可以调用时再定义位置变量,然后通过获取用户输入的值来传给函数中的变量。
数组
数组的定义方式有多种, 最常见的就是函数名=(元素1 元素2 元素3)
查看数组的长度: ${#数组名[*或@]},查看函数的元素内容: ${数组名[*或@]}
数组中元素的赋值,最常用的赋值为: 数组名[下标]=元素值
数组的切片:切片的意思就是将数组元素内容按照设定的内容进行输出
格式:echo ${数组名[*]:下标:需要打印的几个元素值}
例如:将数组内容的第二个元素开始的3个元素输出
echo ${num[*]:1:3}
数组的替换:只是在输出的时候进行替换 (注意:在替换的时候,它找到内容是数组元素中的内容)
格式:echo ${[*]/匹配的内容/替换后的内容} (仅替换每个元素的第一个匹配项)
例如:将输入中的内容3换成10
echo ${num[*]/3/10}