概念
函数是一段完成特定功能的代码片段(块)
在shell中定义了函数,就可以使代码模块化,便于复用代码
注意函数必须先定义才可以使用。
重点
传参 $1,$2
局部变量 local
返回值 return 即 $?
定义函数
方法一:
函数名() {
函数要实现的功能代码
}
方法二:
function 函数名 {
函数要实现的功能代码
}
调用函数
语法
函数名
函数名 参数1 参数2
====================================================================
示例1:初识函数
需求
编写循环脚本,功能菜单
provide these tools:
show disk info(d)
show mem info(m)
show cpu info©
quit(q)
思路
1,编写菜单和判断
2,添加循环
3,添加函数
示例
#!/bin/bash
show_menu() {
cat << EOF
provide these tools:
show disk info(d)
show mem info(m)
show cpu info(c)
quit(q)
EOF
}
while :
do
show_menu
read -p "Input choice: " choice
case $choice in
d)
echo "===========disk info=============="
df -hT
;;
m)
echo "==========meme info==============="
free -m
;;
c)
echo "==========cpu info================="
uptime
;;
q)
break
;;
*)
show_menu
;;
esac
done
====================================================================
示例2:阶乘函数(传参)
需求
制作函数用于阶乘
思路
1 了解阶乘概念 12345=120
2 定义函数
3 引用函数
演示
#!/bin/bash
#定义函数名fun1
fun1() {
#定义阶乘元数
factorial=1
#使阶乘循环
for((i=1;i<=5;i++))
do
#阶乘公式
factorial=$[$factorial*$i]
done
#输出阶乘结果
echo “5的阶乘是:$factorial”
}
fun1
for((i=1;i<=5;i++))
等同于
for i in ·seq 5·
优化
优化1:传参1,让函数能够自定义
#!/bin/bash
fun1() {
factorial=1
for((i=1;i<=$1;i++))
do
factorial=$[$factorial*$i]
done
echo “$1的阶乘是:$factorial”
}
fun1 3
优化2:传参2, 由脚本外部传递参数
提示
函数传参能够在模块化的命令集中,添加自定义部分。参数应加在调用函数的后面。
shell脚本的参数与函数参数不同。是先将SHELL的参数传给函数,函数本身再转换到内部。
#!/bin/bash
fun1() {
factorial=1
for((i=1;i<=$1;i++))
do
factorial=$[$factorial*$i]
done
echo “$1的阶乘是:$factorial”
}
fun1 $1
fun1 $2
fun1 $3
测试:
[root@localhost ~]# bash cc.sh 3 5 10
“3的阶乘是:6”
“5的阶乘是:120”
“10的阶乘是:3628800”
优化3,shell 的写法和其他运算表达式
#!/bin/bash
fun1() {
factorial=1
#for((i=1;i<=$1;i++))
for i in `seq $1`
do
#factorial=$[$factorial*$i]
#let factorial=$factorial*$i
let factorial*=$i
done
echo “$1的阶乘是:$factorial”
}
fun1 $1
====================================================================
示例3:函数传参, 数组传参
1,制作一个简单的阶乘脚本,通过数组给函数传参
#!/bin/bash
#1 先定义一个数组
num=(1 2 3)
#2 定义一个函数
array(){
factorial=1
for i in $* #(重点2)
do
#定义阶层的公式
factorial=$[factorial * $i]
done
echo $factorial
}
#调用函数使用数组(重点1)
array ${num[*]}
测试成功
[root@localhost ~]# bash fun3.sh
6
示例4:函数结果, 赋予数组
需求
用户获赠流量包(每人增加5G),结果运算
通过函数输出到数组
#!/bin/bash
num=(1 2 3)
array(){
#local定义变量仅在函数中有效。
local j
#设置循环的次数,等于索引总数。
for i in $*
do
#定义不同的值乘以5.注意调取值的时候使用的是索引。
outarray[j++]=$[$i * 5]
done
#输出新的数组。
echo "${outarray[*]}"
}
result=`array ${num[*]}`
echo ${result[*]}
测试脚本成功
[root@localhost ~]# bash function_array.sh
5 10 15
总结
函数不仅可以从中调取值,
还可以赋予数组值。
关于i++递增的问题
[root@localhost ~]# aaa[i++]=111
[root@localhost ~]# aaa[i++]=222
[root@localhost ~]# aaa[i++]=333
[root@localhost ~]# echo ${!aaa[@]}
0 1 2
[root@localhost ~]# echo ${aaa[@]}
111 222 333
[root@localhost ~]# ccc[++k]=111
[root@localhost ~]# ccc[++k]=222
[root@localhost ~]# ccc[++k]=333
[root@localhost ~]# echo ${!ccc[@]}
1 2 3
[root@localhost ~]# echo ${ccc[@]}
111 222 333
[root@localhost ~]# aaa[1]=3
[root@localhost ~]# echo ${aaa[@]}
3
[root@localhost ~]# aaa[1]=$[3*5]
[root@localhost ~]# echo ${aaa[@]}
15
[root@localhost ~]# aaa[i++]=20
[root@localhost ~]# aaa[i++]=25
[root@localhost ~]# aaa[i++]=30
[root@localhost ~]# echo ${aaa[@]}
15 20 25 30
true
false
exit
break
continue
shifttrue 真
false 假
shift 使位置参数向左移动,默认移动1位,可以使用shift 2
exit 退出整个程序
break 结束当前循环,或跳出本层循环
continue 忽略 // 跳过本次循环剩余的代码,直接进行下一次循环1
continue,break、shift
需求
通过循环脚本,输入如下效果
A123456789
B123456789
…
D123456789
环境示例
1.编写循环脚本
#!/bin/bash
for i in {A..D}
do
echo $i
for j in {1..9}
do
echo $j
done
done
测试脚本1
[root@localhost ~]# bash for1.sh
A
1
2
3
4
5
6
7
8
9
B
.......
因为默认echo 输出换行符,使用 -n 不输出
解决换行问题
脚本2
#!/bin/bash
for i in {A..D}
do
echo -n $i
for j in {1..9}
do
echo -n $j
done
done
测试已优化的脚本2
[root@localhost ~]# bash for1.sh
A123456789B123456789C123456789D123456789
外循环,添加一条空行语句
#!/bin/bash
for i in {A..D}
do
echo -n $i
for j in {1..9}
do
echo -n $j
done
echo //空行
done
测试最后优化的脚本
[root@localhost ~]# bash for1.sh
A123456789
B123456789
C123456789
D123456789
总结
循环嵌套的规矩是:外部循环一次,内部消化全部
需求
跳出关于5的循环
使用 continue 跳过本次循环命令
#!/bin/bash
for i in {A..D}
do
echo -n $i
for j in {1..9}
do
if [ $j -eq 5 ];then //判断是否为5
continue // 跳过本次循环
fi
echo -n $j
done
echo
done
测试,
[root@localhost ~]# bash for1.sh
A12346789
B12346789C12346789
D12346789
使用break测试
#!/bin/bash
for i in {A..D}
do
echo -n $i
for j in {1..9}
do
if [ $j -eq 5 ];then
break 2
fi
echo -n $j
done
echo
done
测试脚本
[root@localhost ~]# bash for1.sh
A1234
for 循环不定义循环范围,循环参数作为循环范围
#!/bin/bash
for i
do
let sum+=$i
done
echo "sum : $sum"
测试
[root@localhost ~]# bash sum.sh
sum :
[root@localhost ~]# bash sum.sh 1
sum : 1
[root@localhost ~]# bash sum.sh 2
sum : 2
[root@localhost ~]# bash sum.sh 3
sum : 3
[root@localhost ~]# bash sum.sh 1 3
sum : 4
使用while循环,发现停不下来
#!/bin/bash
while [ $# -ne 0 ]
do
let sum+=$1
echo $sum
done
echo "sum : $sum"
测试
[root@localhost ~]# bash sum.sh 1 2
根本停不下来。因为循环为真。
使用shift 移动参数的命令
#!/bin/bash
while [ $# -ne 0 ]
do
let sum+=$1
shift
done
echo "sum : $sum"
测试
[root@localhost ~]# bash sum.sh 1 2
sum : 3
[root@localhost ~]# bash sum.sh 1 2 3
sum : 6
shift总结
shift 1 使参数往左移一位,shift 2 左移2位
使用shift 创建用户,理解参数移位
#!/bin/bash
while [ $# -ne 0 ]
do
useradd $1
echo "$1 is created"
shift
done
测试
[root@localhost ~]# bash shift_user.sh aa bb
aa is created
bb is created