一、函数
1.1、函数的定义(两种方式)
//1.这是一种规范写法
function 函数名 {
command
}
//2.最常用因为最简洁
函数名(){
command
}
函数定义完之后并不会自动执行,需要调用才行。
1.2、 函数返回值
return表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值
使用原则:
- 1、函数一结束就取返回值,因为$?变量只返回执行的最后一条命令的退出状态码
- 2、退出状态码必须是0~255,超出时值将为取余256
例子
#!/bin/bash
function fun1 {
read -p "请输入一个数字" num
echo "this is a function example"
return $[$num*2]
}
fun1
echo $?
1.3、函数的调用
1.直接在脚本里定义函数的代码块后写函数名即可完成调用
#!/bin/bash
function fun1 { //注意 {前有空格
echo "this is a function example"
}
fun1
注意①:函数名必须是唯一,
如果先定义了一个,再用同样的名称定义,第二个会覆盖第一个的功能,
出现了你不想要的结果,所以这里一定要注意不要重名!
注意②:调用函数之前必须先进行定义!
注意③:不一定要在脚本开头就定义函数,只要调用之前定义就可以
2.如果是在其他地方嵌套调用等情况,不可以直接写函数的值,避免无法识别,可以用反撇号引起来,相当于是调用函数的结果。
#!/bin/bash
f1 () {
echo hello
}
f2 () {
echo hi
}
f3 () {
echo "f1 $(f2) `f2` "
}
f3
1.5、函数的作用范围
在 Shell 脚本中函数的执行并不会开启一个新的子 Shell,而是仅在当前定义的 Shell 环境中有效。如果Shell脚本中的变量没有经过特殊设定,默认在整个脚本中都是有效的。在编写脚本时,有时需要将变量的值限定在函数内部,可以通过内置命令local来实现。函数内部变量的使用,可以避免函数内外同时出现同名变量对脚本结果的影响。
- shell脚本中变量默认全局有效
- local命令:将变量限定在函数内部使用
#!/bin/bash
i=99
f1 () {
local i=8
echo $i
}
f2 () {
echo $i
}
f1
f2
echo $i
简答的说,local就是只有在代码块有效,局部的。
1.6、函数的参数
让调用函数时直接使用
#!/bin/bash
add () {
let sum=$1+$2
echo $sum
}
add 2 3
#!/bin/bash
add () {
let sum=$1+$2
echo $sum
}
add $1 $2
这里相当于调用了脚本的参数了,然后把 脚本的位置变量 传递给函数进行计算
1.6.1、案例:阶乘1
5的阶乘为1*2*3*4*5
#!/bin/bash
factorial() {
read -p "你要几的阶乘" m
csz=1
for((i=1;i<=$m;i++))
do
let csz=csz*$i
done
}
factorial
echo "$csz"
1.7、函数的递归
函数自己调用自己的本身
列出目录内文件列表,目录用蓝色表示,文件显示层级关系
显示二级目录
#!/bin/bash
list(){
for i in $1/*
do
if [ -d $i ];then
echo -e "\e[34m$i\e[0m"
list $i " $2"
else
echo "$2$i"
fi
done
}
list $1 $2
1.7.1、案例:阶乘2
#!/bin/bash
fa () {
if [ $1 -eq 1 ]
then
echo 1
else
local tp=$[$1 - 1]
local res=$(fa $tp)
echo $[ $1 * $res ]
fi
}
fa 5
二、数组的定义
数组是存放相同类型数据的集合,在内存中开辟了连续的空间,通常配合循环使用
数组的分类
- 普通数组:不需要声明直接定义,下标索引只能是整数
- 关联数组:需要用declare -A声明否则系统不识别,索引可以是字符串
数组包括的数据类型
数值类型
字符类型:
使用“ ” 或 ‘ ’ 定义
2.1、数组的三种定义方式
- 第一种:直接把要加入数组的元素用小括号括起来,中间用空格分开
格式
数组名= (value0 value1 value2)
num=(11 22 33 44)
${#num} 显示字符串长度
- 第二种:精确的给每一个下标索引定义一个值加入数组,索引数字可以不连续
数组名=([0]=value [1] =value [2] =value...)
num=([0]=55 [1]=66 [2]=77 [4]=88)
- 第三种:先把要加入数组的元素全部先赋值给一个变量,然后引用这个变量加入到数组
格式
列表名="value0 value1 value2....”
数组名=($列表名)
第一种的变形
list=“11 12 13 14”
num=($list)
- 第四种:根据下标定义
数组名[0]="value"
数组名[1]="value"
数组名[2]="value"
数组名[0]=“11”
数组名[0]=“22”
数组名[0]=“33”
2.2、获取数组的长度 、数据
arr_number=(10 20 30 40 50)
arr_length=${#arr_number[*]}
${#arr_number[@]}
echo $arr_length
不加#就是获取数据列表
下标从0开始
2.3、数组元素遍历
#!/bin/bash
arr=(10,20,30,40)
for i in ${arr[*]}
do
echo $i
done
2.4、元素切片
#!/bin/bash
arr=(10 20 3 4 5 6 7 8)
echo ${arr[*]:2:3} #提取从索引2开始的3个元素
echo ${arr[@]:2:2}
echo ${arr[*]:0:2}
2.5、数组(元素)替换
/查找字符/替换字符
并不会替换数组原有内容
#!/bin/bash
arrr=(10,20,10,40)
echo ${arrr[@]/10/2}
echo ${arrr[@]/2/5}
echo ${arrr[@]/0/1}
2.7、数组删除
删除数组
unset arr
指定删除
删除第四个元素
unset arr[4]
2.8、数组排序算法:冒泡排序
方法一
#!/bin/bash
num=(90 70 60 40 50 30)
for ((i=0;i<${#num[*]};i++))
do
for ((j=i+1;j<${#num[*]};j++))
do
if [ ${num[$i]} -gt ${num[$j]} ]
then
temp=${num[$i]}
num[$i]=${num[$j]}
num[$j]=$temp
fi
done
done
echo ${num[*]
方法二
#!/bin/bash
#存入元素
#set -x
k=0
while true
do
read -p "是否存入元素:" doing
if [ $doing == "no" ];then
break
fi
read -p "请输入第$[$k+1]个元素:" key
score[$k]=$key
let k++
done
#外层为轮
for ((i=1;i<${#score[*]};i++));do
#内层为次
for ((j=0;j<${#score[*]}-i ;j++));do
#两数交换
if [ ${score[$j]} -gt ${score[ `expr $j + 1`]} ];then
tmp=${score[`expr $j + 1`]}
score[ `expr $j + 1` ]=${score[$j]}
score[$j]=$tmp
fi
done
done
echo ${score[*]
方法三
#定义一个初始数组
arr=(30 10 50 60 40 20)
echo “原数组的顺序为: ${arr[@]}"
#获取数组的长度
length=${#arr[@]}
#冒泡排序:
#定义比较轮数,为数组长度减一,并且要从1开始
for ( (i=1; i<$length; i++))
do
#确定每次比较的元素下标,比较相邻2个元素,大的往后放,小的往前放,并且每轮比较的次数要随着轮数递减
for ((j=0; j<$length-$i; j++))
do
#获取第一个元素的值
first=${arr[$j]}
#获取第二个元素的值
k=$[$j + 1]
second=${arr[$k]}
#比较第一个元素和第二个元素的值,如果第一个元素值大于第二个元素值则两个元素位置交换
if [ $first -gt $second ];then
#先把第一个元素的值保存在临时变量temp中
temp=${arr[$j]}
#把第二个元素的值赋给第一个元素
arr[$j]=$second
#把原来第一个元素的值赋给第二个元素
arr[$k]=$temp
done
done
echo "排序后新的数组的顺序为:${arr[@]}"
附加
sh [参数] 文件名.sh
- -n 不要执行script,仅查询语法
- -v 在执行script之前,先将script的内容输出到屏幕上
- -x 将使用的脚本的内容输出到屏幕,该参数经常被使用
- -c “string” 从strings中读取命令