Shell编程之函数与数组


一、shell函数

Shell 函数可用于存放一系列的指定。在Shell 脚本执行的过程中,函数被置于内存中,每次调用函数时不需要从硬盘读取,因此运行的速度比较快。在Shell 编程中函数并非是必须的,但使用函数可以对程序进行更好的组织。将一些相对独立额的代码变成函数,可以提高程序可读性和重用性,避免编写大量重复代码。

1.Shell函数定义的基本格式

方法一:基本格式如上,规范写法,其中【function】是可选的,表示该函数的功能,这个是可以省略掉的;函数名后面加一个(),里面没有内容;执行的命令放在{}里面;【return x】的作用是当命令序列执行完毕后返回给系统一个值;也可以省略

[function] 函数名(){
命令序列
[return x] 
}

方法二:最常用,因为最简洁;()等待传参,结尾后面写函数名加传参得参数即}后面加 函数名 参数(可在函数里面定义,也可再外面定义)

函数名 (){
	命令序列
}
[root@yzq function]#sh chuanchan.sh 1 2
3
[root@yzq function]#cat chuanchan.sh 
#!/bin/bash
func () {
sum=0
sum=$[$1+$2]
echo $sum
}
func $1 $2

函数定义完之后并不会自动执行,需要调用才行,好处在于可以写一段功能代码作为函数,有需要就直接调用
定义的时候哪怕出现语法错误也没关系,不调用就不会报错
当然我们写函数最终目的还是为了调用,为了实现某个功能块

2.函数返回值

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

使用原则:
函数一结束就取返回值,因为$?变量只返回执行的最后一条命令的退出状态码
退出状态码必须是0-255,超出时值将取余为256

[root@yzq function]#sh fanhuizi.sh 
输入的数字:2
2
[root@yzq function]#cat fanhuizi.sh 
#!/bin/bash
fanhuizi () {
read -p "输入的数字:" num
return $num
}
fanhuizi
echo $?
[root@yzq function]#sh fanhuizi.sh 
输入的数字:257
1
[root@yzq function]#sh fanhuizi.sh 
输入的数字:256
0

3.函数的调用

直接在脚本里定义函数的代码块后写函数名即可完成调用

[root@yzq function]#sh fc1.sh 
chuanchan.sh  chushihua.sh  fanhuizi.sh  fc1.sh  yum.sh
[root@yzq function]#cat fc1.sh 
#!/bin/bash
chakan ()  {
ls
}
chakan

函数名必须是唯一,如果先定义了一个,再用同样的名称定义,第二个会覆盖第一个的功能,出现了你不想要的结果,所以这里一定要注意不要重名

[root@yzq function]#sh fc2.sh 
nihaoa
[root@yzq function]#cat fc2.sh 
#!/bin/bash
hanshu () {
echo "nihao"
}
hanshu () {
echo "nihaoa"
}
hanshu

调用函数之前必须先进行定义****不一定要在脚本开头就定义函数,只要调用之前的定义就可以

[root@yzq function]#sh fc2.sh 
hao
[root@yzq function]#cat fc2.sh 
#!/bin/bash
hanshu () {
echo "ni"
}
hanshu1 () {
echo "hao"
}
hanshu1

4.函数的作用范围

在Shell 脚本中函数的执行并不会开启一个新的子Shell,而是仅在当前定义的Shell 环境中有效。如果Shell脚本中的变量没有经过特殊设定,默认在整个脚本中都是有效的。在编写脚本时,有时需要将变量的值限定在函数内部,可以通过内置命令local 来实现。函数内部变量的使用,可以避免函数内外同时出现同名变量对脚本结果的影响

函数内部使用local 命令设置变量a,其作用是将变量a限定在函数内部。函数外部同样定义了变量a,内部变量a和全局变量a互不影响。脚本执行时先调用了函数,函数内部变量a为5,所以输出结果是5。调用完函数之后,给变量a赋值为10,再打印外部变量a,所以又输出10.

[root@yzq function]#sh fc3.sh 
5
10
[root@yzq function]#cat fc3.sh 
#!/bin/bash
az () {
local a=5
echo "$a"
}
az
a=10
echo "$a"

5.函数的参数

函数的参数的用法:
函数名称 参数1 参数2 参数3 …

在使用函数参数时,函数名称在前参数在后,函数名和参数之间用空格分割,可以有多个参数,参数使用$1、$2、$3…的方式表示,从第10个参数开始,调用方法为 ${10},不加大括号无法调用成功
1.调用函数时传入两个参数

[root@yzq function]#sh chuanchan.sh 2 2
4
[root@yzq function]#cat chuanchan.sh 
#!/bin/bash
func () {
sum=0
sum=$[$1+$2]
echo $sum
}
func $1 $2

6.函数的递归

Shell 也可以实现递归函数,就是可以调用自己本身的函数。在Linux系统上编写Shell 脚本的时候,经常需要递归遍历系统的目录,列出目录下的文件,逐层递归列出,并对这些层级关系进行展示。

[root@yzq function]#sh fc2.sh 
ni
hao
ni hao
[root@yzq function]#cat fc2.sh 
#!/bin/bash
hanshu () {
echo "ni"
}
hanshu
hanshu1 () {
echo "hao"
}
hanshu1
hanshu2 () {
echo "$(hanshu) $(hanshu1)"
}
hanshu2

函数递归实现阶乘计算

[root@yzq function]#sh jiecheng.sh 5
120
[root@yzq function]#cat jiecheng.sh 
#!/bin/bah
jc () {
if [ $1 -eq 1 ]
 then
  echo 1
 else
  num=$[$1-1]
  ji=$(jc $num)
  echo "$[ $1 * $ji ]"
fi
}
jc $1

递归遍历目录,使目录和普通文件颜色不一样

[root@yzq function]#sh bl.sh /home/
/home//123 
/home//lisi 
/home//zhangsan 
[root@yzq function]#cat bl.sh 
#!/bin/bash
function bl(){
for i in `ls  $1`
do
if [  -d $1"/"$i ];then
echo -e "\033[34m$1/$i \033[0m"
bl $1"/"$i
else
echo -e  "\e[1;31m   $1/$i\e[0m"
fi

done
}

bl $1

二、shell数组

数组的定义

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

数组的分类

普通数组:不需要声明直接定义,下标索引只能是整数
关联数组:需要用declare -A声明否则系统不识别,索引可以是字符串

1.数组定义方法

1.1 方法一

直接把要加入数组的元素用小括号括起来,中间用空格分开
使用 echo $(a[/@]) 用或者@可以查看定义的数组里面的元素

[root@yzq mnt]#a=(1 2 3 4)
[root@yzq mnt]#echo ${a[*]}
1 2 3 4

1.2 方法二

精确的给每一个下标索引定义一个值加入数组,索引数字可以不连续

[root@yzq mnt]#car[0]=gtr
[root@yzq mnt]#car[1]=suv
[root@yzq mnt]#car[2]=tt
[root@yzq mnt]#echo ${car[@]}
gtr suv tt

[root@yzq mnt]#b=([0]=10 [1]=20 [2]=30)
[root@yzq mnt]#echo ${b[@]}
10 20 30

1.3 方法三

先把要加入数组的元素全部先赋值给一个变量,然后引用这个变量加入到数组

[root@yzq mnt]#c="1 2 3 4"
[root@yzq mnt]#d=$c
[root@yzq mnt]#echo ${d[@]}
1 2 3 4

1.4 方法四

可以把命令的结果用小括号括起来添加到数组,那么数组会以空格或者制表符区分每一个元素

[root@yzq mnt]#num=`ls`
[root@yzq mnt]#echo ${#num[*]}
95
[root@yzq mnt]#echo ${num[o]}
{0-9}txt 0txt 1txt 2txt 3txt 4txt 5txt 6txt 7txt 8txt 9txt atxt Atxt btxt Btxt ctxt Ctxt dtxt Dtxt etxt Etxt ftxt Ftxt gtxt Gtxt htxt Htxt itxt Itxt jtxt Jtxt ktxt Ktxt ltxt Ltxt mtxt Mtxt nginx.access.log-2021013 ntxt Ntxt otxt Otxt ptxt Ptxt qtxt Qtxt rtxt Rtxt shuzu stxt Stxt test.txt ttxt Ttxt txt utxt Utxt vtxt Vtxt wtxt Wtxt xtxt Xtxt ytxt Ytxt ztxt Ztxt

数组的格式

arr=(11 22 33 44)
数组名称:arr
数组元素:11,12,12,14,数组元素默认是以空格分隔的
数组长度:4,有4个元素
数组下标:每个数组元素都有一个下标索引,一般从0开始,33是数组第三个元素,但是它的下标索引是2

2.数组操作

2.1 元素切片

${数组名[*]:起始位置:长度}
[root@yzq ~]# echo ${a[*]:0:1}
1

2.2 元素替换

${数组名[*]/查找字符/替换字符}
[root@yzq ~]# echo ${a[*]/1/11}
11 2 3 4


2.3 元素删除


```bash
[root@yzq mnt]#unset a[0]
[root@yzq mnt]#echo ${a[*]}
2 3 4

3.示例

3.1 冒泡法排序

[root@yzq shuzu]#sh maopao.sh 
10 20 40 50 70
[root@yzq shuzu]#cat maopao.sh 
#!/bin/bash
a=(10 20 40 70 50)
#定义比较轮数,轮数为数组长度减一,从0开始
for ((i=1;i<${#a[*]};i++))
do
#确定比较元素的大小,较大的往后放,不断的比较
   for ((j=0;j<${#a[*]}-$i;j++))
   do
#如果第一个元素比第二个元素大就交换
        if [ ${a[j]} -gt ${a[j+1]} ];then
#把大的元素赋值给b
        b=${a[j]}
#交换a组的位置,小的那个往前排
        a[j]=${a[j+1]}
#大的那个往后排
        a[j+1]=$b
        fi
   done
done
echo ${a[*]}

3.2 将数组中不足60的删除

[root@yzq shuzu]#sh shanchu.sh 
60 70 12 30
[root@yzq shuzu]#cat shanchu.sh 
#!/bin/bash
a=(10 20 50 60 70 12 30)
for ((i=0;i<${#a[*]};i++))
do
        if [ ${a[i]} -lt 60 ];then
            unset a[i]
        fi
done
echo ${a[*]}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值