shell编程之函数和数组

本文详细介绍了Shell脚本的调试技巧,包括echo命令的转义符使用和bash命令的参数解析。接着,文章重点讲解了Shell函数的定义、返回值、传参以及变量的作用范围,并给出了实用的函数应用示例。此外,还探讨了Shell数组的分类、定义方式和应用场景,以及冒泡排序的基本思想和实现。通过对这些概念的深入理解,有助于提升Shell脚本编程能力。
摘要由CSDN通过智能技术生成

目录

前言

一、shell脚本调试

1、echo命令及转义符含义

2、bash命令

3、set命令

二、shell函数

1、函数简介

2、函数返回值

3、函数传参

4、shell函数变量的作用范围

5、函数其他应用

三、shell数组

1、数组的分类:

2、数组的定义方式

3、数组应用场景

四、冒泡排序

1、冒泡排序基本思想

2、冒泡排序算法应用

总结


前言

       一些命令序列是需要反复调用执行的,若每次使用同一命令就重复写一遍,就会导致代码量很

大,行数特别多。为解决该问题可以将命令序列按格式写在一起,以便可以重复的使用。

一、shell脚本调试

1、echo命令及转义符含义

◆echo -n     表示不换行输出

◆echo -e     输出转义符,将转义后的内容输出到屏幕上

常用转义符:

◆\b   转义后相当于按退格键(backspace) ,但前提是"b"后面存在字符; "\b"表示删除前一个字符,

"\bb"表示删除前两个字符。

◆\c   不换行输出,在"\c"后面不存在字符的情况下,作用相当于echo-n;但是当"\c"后面仍然存在字符

时, "\c"后面的字符将不会被输出。

◆\n   换行,被输出的字符从"\n"处开始另起一行

◆\f   换行,但是换行后的新行的开头位置连接着上一行的行尾;

◆\v   与\f相同

◆\t   转以后表示插入tab,即横向制表符;

◆\r   光标移至行首,但不换行,相当于使用"\r"以后的字符覆盖"1r"之前同等长度的字符;但是当"r"后面

不存在任何字符时, "\r"前面的字符不会被覆盖

◆\\   表示插入""本身

2、bash命令

命令格式:sh [-nvx] 脚本名

bash常用参数的具体含义为:

◆ -n:不会执行该脚本,仅查询脚本语法是否有问题,如果没有语法问题就不显示任  何内容,如果有问题会提示报错。

◆ -v:在执行脚本时,先将脚本的内容输出到屏幕上然后执行脚本,如果有错误,也  会给出错误提示。

◆-x:将执行的脚本内容输出到屏幕上,这个是对调试很有用的参数。  当脚本文件较长时,可以使用 set 命令指定调试一段脚本。

3、set命令

◆set -X 开启调节模式

◆set +x 关闭调节模式

二、shell函数

1、函数简介

Shell函数定义的基本格式如下

                                                

        其中[function]是可选的,表示该函数的功能,这个是可以省略掉的;函数名后面加一个

(),里面是没有内容的;而我们执行的命令序列放在{ }里面的,[return x]的作用是当命令序列执

行完后返回给系统一个值,该项也是可以省略的。函数定义完成后并不会自动执行,在脚本中调用

函数的方式是直接输入函数名即可,有时候还需要输入一些参数。

[root@kang mytext]# vim hanshuxx.sh 
#!/bin/bash
function fun1 {
echo "this is a function"   #简单的函数创建
}
fun1  #函数调用

2、函数返回值

return表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值。

使用原则:

①、函数一结束就取返回值,因为$?变量只返回执行的最后一条命令的退出状态码。

②、退出状态码必须是0~255,超出时值将为除以256取余。

[root@kang mytext]# vim hanshuxx.sh
#!/bin/bash
function test {
read -p "请输入数字:" num
return "$[$num*2]"
}
test
echo $?
[root@kang mytext]# bash test1.sh 
请输入数字:2
4
[root@kang mytext]#

3、函数传参

       传参就是向函数传递参数,

[root@kang mytext]# vim test1.sh 
#!/bin/bash
sum () {
read -p "请输入第个参数:" NUM1
read -p "请输入第二个参数:" NUM2
echo "你输入的两个数为:$NUM1和$NUM2"
SUM=$(( $NUM1+$NUM2 ))
echo "两个数的和为: $SUM" 
}
sum
[root@kang mytext]# bash test1.sh 
请输入第个参数:12
请输入第二个参数:31
你输入的两个数为:12和31
两个数的和为: 43
[root@kang mytext]#

4、shell函数变量的作用范围

        函数在Shell脚本中仅在当前Shell环境中有效,Shell脚本中变量默认全局有效,将变量限定在

函数内部使用local命令即可。函数内是局部 函数外是全局。

[root@kang mytext]# vim test1.sh 
#!/bin/bash
fun () {
local a
a=5
echo $a
}
a=9
fun
echo $a
[root@kang mytext]# bash test1.sh 
5          #函数里面定义的5只在函数里有效
9,        #而函数外的$a还是之前最开始定义的9

        上述脚本中fun函数内部使用了local命令设置变量a,其作用是将变量a限定在函数内部。fun

函数外部同样定义了变量a,内部变量a和全局变量a互不影响。脚本执行时先调用了函数fun,函数

内部变量a为5,所以输出结果是5。调用完函数之后,给变量a赋值为9,再打印外部变量a,所以

又输出9。

5、函数其他应用

①、函数目录递归

       函数自己调用自己本身。列出目录内文件列表,目录用蓝色表示,文件显示层级关系。

[root@kang mytext]# vim hanshuxx.sh
#!/bin/bash
list ()  {
for a in $1/*      #遍历目录
do
        if [ -d $a ]
        then
        #判断若为目录则按格式输出目录名称并继续调用函数遍历这个目录
                echo -e "\e[34m$a\e[0m"
                list $a "$2"
        else
        #判断为文件则直接按照格式输出文件名称
                echo "$2$a"
        fi
done
}

list "/mytext/" ""
##调用函数,第一个参数为要进行遍历的目录,第二个参数为格式设定,区分目录层级
[root@kang mytext]# bash linshi.sh
/mytext//20210911-01.sh
/mytext//20210911-ftp.sh
/mytext//aa      #此处目录显示为蓝色, 
/mytext//aa/a.txt   #其它文件显示层级关系
/mytext//aa/b.txt
/mytext//DNS_xx.sh
/mytext//first.sh
/mytext//forxx.sh
…………

②、函数的阶乘

        正整数的阶乘是所有小于及等于该数的正整数的积,并且0的阶乘为1。阶乘是一个递推定

义,n!=n*(n-1)!;人为规定,因为1!=1,根据1!=1*0!,所以0!=1而不是0。

[root@kang mytext]# vim hanshuxx.sh
#!/bin/bash
fa ()
{
  if [ $1 -eq 1 ];then echo 1
  else
     local tp=$[ $1 - 1 ]
     local res=$(fa $tp)
     echo $[ $1 * $res ]
  fi
}
read -p "请输入阶乘起始值:" num
res=$(fa $num)
echo $res
[root@kang mytext]# bash linshi.sh
请输入阶乘起始值:5
120
[root@kang mytext]#

三、shell数组

数组是存放相同类型数据的集合。在内存中开辟了连续的空间,通常配合循环使用。

1、数组的分类:

普通数组:不需要声明直接定义,下标索引只能是整数

关联数组:需要用declare -A声明,否则系统不识别,索引可以是字符串

2、数组的定义方式

①、第一种:直接把要加入数组的元素用小括号括起来,中间用空格分开。

[root@kang ~]# num=(11 22 33 44)
[root@kang ~]# echo ${num[@]}
11 22 33 44

数组名= (value0 value1 value2)

②、第二种:精确的给每一个下标索引定义一个值加入数组,索引数字可以不连续。

[root@kang ~]# num=([0]=55 [1]=66 [2]=77 [4]=88)
[root@kang ~]# echo ${num[@]}
55 66 77 88
[root@kang ~]#

数组名=([0]=value [1] =value [2] =value...)

③、第三种:先把要加入数组的元素全部先赋值给- 一个变量,然后引用这个变量加入到数组。

[root@kang ~]# list="10 16 30 40 50"
[root@kang ~]# num=($list)
[root@kang ~]# echo ${num[@]}
10 16 30 40 50
[root@kang ~]#

④、第四种:使用变量名加索引,给索引所在位置赋值。

[root@kang ~]# num[0]=2
[root@kang ~]# num[1]=5
[root@kang ~]# num[4]=6
[root@kang ~]# num[5]=7
[root@kang ~]# echo ${num[@]}
2 5 6 7
[root@kang ~]#

3、数组应用场景

[root@kang ~]# echo ${num[@]}   #获取数据列表
2 5 6 7
[root@kang ~]# echo ${num[*]}   #获取数据列表
2 5 6 7
[root@kang ~]# echo ${#num[@]}   #加#号获取数组长度
4
[root@kang ~]# echo ${num[1]}    #读取某索引对应的赋值
5
[root@kang ~]# echo ${num[@]:0:2}
2 5
[root@kang ~]# echo ${num[@]:1:2}  #显示从第1个索引下标开始往后的两位
5 6
#数组切片,第一个冒号后跟的是索引号;第二个冒号后跟的为长度
[root@kang ~]# echo ${num[@]/5/9}  #将数组中元素5替换成元素9
2 9 6 7
[root@kang ~]# echo ${num[@]} #紧接着查看数组原来的元素
2 5 6 7
#注意:这里替换是临时的,不会影响原数组元素
[root@kang ~]# unset num[4]   #unset加上索引会删除下标对应赋值
[root@kang ~]# echo ${num[@]}
2 5 7
[root@kang ~]# unset num    #删除整个数组
[root@kang ~]# echo ${num[@]}

[root@kang ~]#

 数组遍历

[root@kang mytext]# vim shuzu.sh 

#!/bin/bash
arr=(1 2 3 4 5 6)  #定义一个数组
for a in "${arr[@]}"   #遍历循环数组中的元素
do
echo $a
done
for a in "${arr[*]}"    #这里可以比较@和*的区别
do
echo $a
done
[root@kang mytext]# bash shuzu.sh 
1
2
3
4
5
6            #当使用@时,数组中元素是单独的个体
1 2 3 4 5 6    #当使用*号时,数组显示出来的元素是一个整体

四、冒泡排序

1、冒泡排序基本思想

        冒泡排序的基本思想是对比相邻的两个元素值,如果满足条件就交换元素值,把较小的元素

移动到数组前面,把大的元素移动到数组后面(也就是交换两个元素的位置),这样较小的元素就

像气泡一样从底部上升到顶部。

        冒泡算法由双层循环实现,其中外部循环用于控制排序轮数,一般为要排序的数组长度减1

次,因为最后一次循环只剩下一个数组元素,不需要对比,同时数组已经完成排序了。而内部循环

主要用于对比数组中每个相邻元素的大小,以确定是否交换位置,对比和交换次数随排序轮数而减

少。

2、冒泡排序算法应用

[root@kang mytext]# vim paixu.sh 

#!/bin/bash

###############冒泡排序从小到大排.........................
arr=(90 70 50 60 30 40)  #定义数组
echo "array:${arr[*]}"   #显示数组
lt=${#arr[*]}            #将数组长度显示并赋值给lt
for ((i=1;i<$lt;i++))     #定义第一个数比较总轮数比数组长度小.从第一轮开始即i=1
  do
#确定比较元素得位置,比较相邻两个元素,较大得数往后放,小的数前放,并且每轮比较次数要随着轮>数递减。
        for ((j=0;j<$lt-i;j++))  #定义每次比较后元素的下标
          do
                first=${arr[$j]}    #定义第一个元素的值;第一次下标为0的数赋值给第一个变量
                k=$[$j+1]           #关联第一个下标,比第一个下标多1位
                second=${arr[$k]}   #定义第二个元素的值;前一位数的后一位数赋值给第二个变量
#若第一个元素比第二个元素大,就互换位置
                  if [ $first -gt $second ];then  #比较两个变量的大小
                        tmp=$first        #添加临时变量,把大的值赋值给临时变量名
                        arr[$j]=$second   #把小的值赋值给数组下标小的
                        arr[$k]=$tmp   #把临时变量(大的值)值赋值给下标+1位对应值
                  fi
        done
done
echo "new-array:${arr[*]}"
[root@kang mytext]# bash paixu.sh 
array:90 70 50 60 30 40   
new-array:30 40 50 60 70 90
[root@kang mytext]#

总结

       未完待续。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值