Shell编程—函数、shell数组、shell脚本调试、冒泡排序

前言

学习函数,教我们如何将一段经常需要使用的代码封装起来,在需要使用时可以直接调用。

一、Shell函数

将命令序列按格式写在一起,可方便重复使用命令序列

1.1 Shell函数定义

[ function] 函数名(){ 
  命令序列
  [return x]      #使用return或exit可以显式地结束函数
}                 #break:退出整个循环体
                  #continue:退出本次循环

1.2 调用函数的方法

函数名 [参数1] [参数2]

例1:两个数求和

[root@server2 ~]# vi sum.sh
#!/bin/bash
# 函数求和
sum(){             #函数名:sum; ():不带参数
    read -p "第一个数:" num1
    read -p "第二个数:" num2
    echo "您输入这两个数为 $num1和$num2"  
    sum=$(($num1+$num2))
    echo "这两个数的和为:$sum"
}
sum          #调用函数
[root@server2 ~]# chmod +x sum.sh
[root@server2 ~]# ./sum.sh
第一个数:10
第二个数:23
您输入这两个数为 1023
这两个数的和为:33

例2:

[root@server2 ~]# vim function
servicectl_usage(){
   echo "Usage:service <service-name> <start|stop|restart|reload|status>"
   return 1
}
chk_centos_ver(){
   grap "CentOS.*release 7." /etc/centos-release &> /dev/null && echo "7"
   grap "CentOS.*release 6." /etc/centos-release &> /dev/null && echo "6"
   grap "CentOS.*release 5." /etc/centos-release &> /dev/null && echo "5"
}
servicectl(){
[[ -z $1 || -z $2 ]] && servicectl_usage
[ $(chk_centos_ver)=="7" ] && systemctl $2 $1 || service $1 $2
}
[root@server2 ~]# chmod +x function
[root@server2 ~]# source function    #成为环境变量
[root@server2 ~]# echo 'source /root/function' >> ~/.bashrc

1.3 函数的作用范围

函数在Shell脚本中仅在当前Shell环境中有效
Shell脚本中变量默认全局有效
将变量限定在函数内部使用local命令

例:

[root@client2 ~]# vi fun_scope. sh
myfun( ){        #定义一个函数myfun
    local i       #局部变量
    i=8              #局部变量赋值
    echo $i
}
i=9
myfun    #变量调用,8
echo $i   #i为9
[ root@client2 ~]#chmod +x fun_scope.sh
[root@client2 ~]# ./fun_scope. sh
8
9

修改验证:

[root@client2 ~]# vi fun_scope. sh
myfun( ){        #定义一个函数myfun
    i=10              #全局变量赋值
    echo $i
}
i=9
myfun       #全局变量调用,i=9也会被覆盖为10
echo $i     #i为10
[ root@client2 ~]#chmod +x fun_scope.sh
[root@client2 ~]# ./fun_scope. sh
10
10

二、函数的参数

2.1 参数的用法

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

2.2 参数的表示方法

$1 $2 $3 … ${10} ${11} …
例:

[ root@client2 ~]# vi write_log. sh
#!/ bin/ bash
# 文件内容写入
mydir=/data
outfile=${mydir}/my . log
[ -e "${mydir}" ] ll mkdir ${mydir}   #目录或文件是否存在,或者创建一个
appendfile (){               #定义一个函数
    echo "$2" >> $1          #"$2"追加到$1,$1空的
}
appendfile ${outfile} "first line content."     #first line content.追加到${outfile}内
appendfile ${outfile} "second line content."    #second line content.追加到${outfile}[ root@client2 ~]# chmod +x write_log.sh
[ root@client2 ~]# ./write_log.sh
[root@client2 ~]# cat /data/my . log    #查看
first line content.
second line content.

三、递归函数

调用自己本身的函数
例:

[root@client2 ~]# vi fun_recursion. sh
list_files ( ){
    for f in `ls $1`   #$1为下面解释/var/log
    do
       if [ -d "$1/$f” ]      #查看/var/log下$f是否为目录
       then echo "$2$f"    #显示$f,$2下面解释是空
       list_files "$1/$f" "    $2"   
#再次调用函数,$1"$1/$f",$2"    $2",带入前面循环,查看"$1/$f/$f"是否为目录,是则显示"     $2",一直循环
       else     #别的,查看不是目录的
       echo "$2$f"     #显示"$f"
       fi
done
}
list_files " /var/log" ""
[ root@client2 ~]# cd /var/log/
[root@client2 log]# mkdir -p a/b/c      #递归创建目录
[root@client2 log]# cd a/b/c/
[root@client2 c]# vi 1.txtl     #c目录里创建文件
111111111111111111111
[root@client2 c]# cd       #切换到宿主目录
[ root@client2 ~]# chmod +x ./fun_recursion. sh
[ root@client2 ~]# ./fun_recursion. sh

在这里插入图片描述

四、Shell数组

应用场景包括:
获取数组长度
获取元素长度
遍历元素
元素切片
元素替换
元素删除

4.1数组定义方法

例:

方法一:数组名=(value0 value1 value2 ...)

方法二:数组名=([0]=value [1]=value [2]=value ...)    #[0] [1]...这些为下标,代表位置

方法三:列表名="value0 value1 value2 ..."
              数组名=($列表名)

方法四:数组名[0]="value"
       数组名[1]="value"
       数组名[2]=”value"

4.2数组包括的数据类型

数值类型
字符类型
使用""或"定义

4.3 Shell数组操作

1.获取数组数值

${数组名[@/*]}   #@或*

例:

[root@server2 ~]# a=(1 2 3 4 5)
[root@server2 ~]# echo ${a[*]}
1 2 3 4 5

2.获取数组长度

${#数组名[@/*]}

例:

[root@server2 ~]# a=(1 2 3 4 5)
[root@server2 ~]# echo ${#a[*]}    
5

3.读取某下标赋值

${数组名[下标]}    #下标排序是从0号位开始排序的

例:

[root@server2 ~]# a=(1 2 3 4 5)
[root@server2 ~]# echo ${a[0]}        #显示0号位
1

4.数组遍历
例:

[root@client2 ~]# vi num1.sh
#!/bin/bash
# 数组循环
a=(1 2 3 4 5)
for num in ${a[*]}      #$num是数组里的一个值
do
    echo $num
done
[root@client2 ~]# chmod +x num1.sh
[root@client2 ~]# ./num1.sh
1
2
3
4
5

5.数组切片

${数组名[@/*]:起始位置:长度}

例:

[root@client2 ~]# vi num1.sh
#!/bin/bash
# 数组循环
a=(1 2 3 4 5)
for num in ${a[*]:1:2}      #$num是数组里0号位为起始位置,长度2的数
do
    echo $num
done
[root@client2 ~]# chmod +x num1.sh
[root@client2 ~]# ./num1.sh
2
3

6.数组的替换 #数值没有真正被替换,只是输出显示

${数组名[@/*]/查找字符/替换字符}

例:

[root@client2 ~]# a=(1 2 3 4 5)
[root@client2 ~]# echo ${a[@]/2/22}   #查找下标2替换为22
1 22 3 4 5
[root@client2 ~]# echo ${a[*]}    #数值没有被真正替换
1 2 3 4 5
[root@client2 ~]# a1=${a[*]/2/22}
[root@client2 ~]# echo $al
1 22 3 4 5

7.数组删除
unset
例:

[root@client2 ~]# a=(1 2 3 4 5)
[root@client2 ~]# echo ${a[@]}
1 2 3 4 5
[root@client2 ~]# unset a
[ root@client2 ~]# echo ${a[@]}
                                     #空的,已删除

五、Shell脚本调试

echo命令
bash命令
命令语法:sh [-nvx] 脚本名
常用选项-n、-v、-x
-n:不会执行该脚本,仅查询脚本语法是否有问题,如果没有语法问题就不显示任何内容,如果有问题会提示报错。
-v:在执行脚本时,先将脚本的内容输出到屏幕上然后执行脚本,如果有错误,也会给出错误提示。
-x:将执行的脚本内容输出到屏幕上,这个是对调试很有用的参数。
set命令
set-x:开启调节模式
set+x:关闭调节模式

例:

[root@client2 ~]# vi grade.sh
#!/bin/bash
set -x //开启调试模式
read -p "请输入您的分数(0-100):" GRADE
if [ $GRADE -ge 85 ]&&[ $GRADE -le 100 ]
then
echo "$GRADE 分!优秀" set +x //关闭调试模式
elif [ $GRADE -ge 70 ] && [$GRADE -le 84 ]
then
echo "$GRADE 分,合格"  else
echo "$GRADE 分?不合格"
fi
[root@client2 ~]# sh -n grade. sh     #不会执行该脚本,语法没错误
[root@client2 ~]# sh -v grade. sh       #执行脚本输出到屏幕
# ! /bin/ bash
set -x //开启调试模式
read -p "请输入您的分数(0-100):" GRADE
+ read -p '请输入您的分数(0-100):' GRADE
请输入您的分数(0- 100 ):85
if [ $GRADE -ge 85 ]&&[ $GRADE -le 100 ]
then
echo "$GRADE 分!优秀" set +x //关闭调试模式
elif [ $GRADE -ge 70 ]&&[ $GRADE -le 84 ]
then
echo "$GRADE 分,合格" else
echo "$GRADE 分?不合格"
fi
+ '[’ 85 -ge 85 ']'
+ '[’ 85 -le 100 ']'
+ echo '85分!优秀' set +x $ '//\345\205\263\351\227\255\350\22031350\257\2251346\2501241\3451274\217'
85!优秀set +x //关闭调试模式
[root@client2 ~]# sh grade.sh
+ read -p '请输入您的分数(0-100): ' GRADE
请输入您的分数(0-100): 70
+ '[’ 70 -ge 85 ']'
+ '[’ 70 -ge 70 ']'
+ '[' 70 -le 84 ']'
+ echo '70分,合格' else
70,合格 else
+echo '70分?不合格'
70?不合格

六、冒泡排序

注:数值的长度-排序的轮数=比对的次数

解析:通过对数据循环排序,得出数值大小,进行排序

排序流程

score =10  5  1  100  70  60

第一轮 比较了5次
10 5 1 100 70 60
5 10 1 100 70 60 1次 #5和10比
5 1 10 100 70 60 2次 #10和1比
5 1 10 100 70 60 3次 #10和100比
5 1 10 70 100 60 4次 #100和70比
5 1 10 70 60 100 5次 #100和60比  得出最大数值

第二轮 比较了4次
5 1 10 70 60
1 5 10 70 60 1次
1 5 10 70 60 2次
1 5 10 70 60 3次
1 5 10 60 70 4次 得出倒数第二大数值

第三轮 比较了3次
1 5 10 60 得出倒数第三大数值

第四轮 比较了2次
1 5 10 得出倒数第四大数值

第五轮 比较了1次
1 5 得出倒数第五大数值
例1:

[root@client2 ~]# vi maopao1.sh
#!/ bin/ bash
# 冒泡排序
score=(70 10 40 100 5 60)
for ((i=1;i<${#score[*]};i++))       #排序轮数
do
      for ((j=0 ; j<${#score[*]}-$i; j++))      #因为比对次数从0开始,所以<数值的长度-排序的轮数
      do
          if [ ${score[ j ]} -gt ${score[ j+1 ]} ]        #当前面的数大于后面的数的时候
          then temp=${score[ j ]}                              #添加temp数值为前面大的数值
                  score[ j ]=${score[ j+1 ]}           #把后面大的数值替换前面小的数值
                  score[ j+1 ]=$temp                 #后面大的数值=原来前面小的数值
          fi
       done
done
echo ${score[*}          #显示输出score全部数值
[root@client2 ~]# chmod +x maopao1.sh
[root@client2 ~]# ./maopao1.sh
5 10 40 60 70 100

例2: 键盘输入冒泡排序

[root@client2 ~]# vi maopao1.sh
#!/ bin/ bash
# 键盘输入冒泡排序
k=0      #数组元素第0while true     #条件为真时一直循环
do
     read -p"是否需要输入数值? " do
     if [ $do == "no"]    #当输入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++))      #因为比对次数从0开始,所以<数值的长度-排序的轮数
      do
          if [ ${score[ j ]} -gt ${score[ j+1 ]} ]        #当前面的数大于后面的数的时候
          then temp=${score[ j ]}                              #添加temp数值为前面大的数值
                  score[ j ]=${score[ j+1 ]}           #把后面大的数值替换前面小的数值
                  score[ j+1 ]=$temp                 #后面大的数值=原来前面小的数值
          fi
       done
done
echo ${score[*}          #显示输出score全部数值 
[root@client2 ~]# chmod +x maopao1.sh
[root@client2 ~]# ./maopao1.sh
是否需要输入数值? y    #只要不输入no就继续
请输入第1个元素5
是否需要输入数值? y
请输入第2个元素22
是否需要输入数值? y
请输入第3个元素15
是否需要输入数值? y
请输入第4个元素3
是否需要输入数值? y
请输入第5个元素120
是否需要输入数值? y 
请输入第6个元素50
是否需要输入数值? no
3 5 15 22 50 120
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值