Shell编程之循环语句与函数

引言
Shell作为一种脚本编程语言,包含循环、分支等其他程序控制结构,从而能够轻松完成更加复杂的工作。本文主要讲了for、while语句的具体用法。

一、循环语句

1、for循环语句

使用 for 循环语句时,需要指定一个变量及可能的取值列表,针对每一个不同的取值重复执行相同的命令序列,直到变量值用完退出循环。

for 循环语句的语法结构如下:

for 变量名 in 取值列表
do
    命令序列
done

for 语句的执行流程

  • 首先将列表中的第1个取值赋给变量,并执行 do···done 循环体中的命令序列
  • 然后将列表中的第2个取值赋给变量,并执行循环体中的命令序列……
  • 以此类推,直到列表中的所有取值用完,最后将跳至 done 语句,表示结束循环

1.1 计算整数和

用户随机输入一个小于100的整数,并计算从1到该数之间所有整数的和

1.2 列出奇偶数

1.3 批量添加、删除用户
添加用户

调用这个文件,根据这个文件来创建用户名

 

创建用户成功

删除用户


1.4 根据IP地址列表检查主机状态

 

调用ip.txt

 

查看主机状态


1.5 密码验证

 

1.6 九九乘法表

 

2、while语句

for循环语句非常适用于列表对象无规律,且列表来源已固定(如某个列表文件)的场合。而对于要求控制循环次数、操作对象按数字顺序编号、按特定条件执行重复操作等情况,则更适合使用另一种循环—while语句。

  • 使用 while循环语句时,可以根据特定的条件反复执行一个命令序列,直到该条件不再满足时为止。但是在脚本应用中,应该避免出现死循环的情况,否则后边的命令操作将无法执行。
  • 循环体内的命令序列中应包括修改测试条件的语句,以便在适当的时候使测试条件不再成立,从而结束循环。

while循环语句的语法结构如下所示:

while 条件测试操作
do
    命令序列
done

执行流程:

  • 首先判断 while 后的条件测试操作结果,如果条件成立,则执行 do···done 循环体中的命令序列
  • 返回 while 后再次判断条件测试结果,如果条件仍然成立,则继续执行循环体
  • 再次返回到 while 后,判断条件测试结果…如此循环
  • 直到 while 后的条件测试结果不再成立为止,最后跳转到 done 语句,表示结束循环

2.1 列出1-100之间能被3整除的数

 vim zhengchu.sh 
 
#!/bin/bash
i=1                        //定义变量i=1
while [ $i -le 100 ]    //重复测试$1是否小于等于100,直至$i等于100
        do                //命令列表
        if [[ $i%3 -ge 0 ]]    //条件检测 $i取余3,是否等于0
        then                //条件成立
                echo "$i"    //输出 $i的值
        fi                    //结束判断
        let i++                //每次循环i+1
done                        //结束循环

 


把-ge换成-ne就是不等于


2.2 猜数字

[root@zhang home]# vim text2.sh 
 

#!/bin/bash
cnum=520
while true
do
read -p "请输入数字:" num
    if [ $num -eq $cnum ]
    then
        echo "你猜对了"
        break
    elif [ $num -gt $cnum ]
    then
        echo "你猜大了"
    elif [ $num -lt $cnum ]
    then
        echo "你猜小了"
    fi
done


 

2.3 猜商品价格

[root@zhang while]# vim pricegame.sh 
#!/bin/bash
PRICE=$(expr $RANDOM % 1000)
a=0
echo "商品实际价格范围为0-999,猜猜看是多少?"
while true
do
read -p "请输入你猜测的价格数目:" INT
let a++

if [ $INT -eq $PRICE ]
     then
     echo "恭喜你答对了,实际价格是 $PRICE"
     echo "你总共猜测了 $a 次"
     exit 0
elif [ $INT -gt $PRICE ]
then
     echo "你猜高了!"
else
     echo "你猜低了!"
fi
done


2.4 商场购物

#!/bin/bash
i=1
sum=0
while [ $i -le 3 ]
do
   echo "进入第$i家商店"
   read -p "是否进入看看(yes/no)" doing
   while [ $doing = "yes" ]
    do
       echo "1:衣服 ¥200"     
       echo "2:鞋子 ¥999"
       echo "3:帽子 ¥120"
       echo "4:裤子 ¥279"
       read -p "请选择你需要购买的商品的序列号:" num

       case $num in
       1)
         echo "衣服购买成功"
         expr $[sum+=200] &>/dev/null
       ;;


       2)
         echo "鞋子购买成功"
         expr $[sum+=999] &>/dev/null
       ;;
       3)
         echo "帽子购买成功"
         expr $[sum+=120] &>/dev/null
       ;;
       *)
         echo "裤子购买成功"
         expr $[sum+=279] &>/dev/null

       esac
            read -p "是否进行购买(yes/no)?" doing
       done
       let i++
       if [ $doing = "no" ]
       then continue
       fi
done
echo "购物总价为:$sum"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 

3、until语句

重复测试某个条件,只要条件不成立则反复执行

语法结构如下所示:

until 条件测试操作
do
    命令序列
done


3.1 计算1~50的和值

[root@zhang until]# vim 50.sh
 

#!/bin/bash
i=1                             //定义变量i=1
sum=0                   
until [ $i -eq 51 ]             //$i等于51时停止执行
do      
        sum+1=i          //sum=sum+i
        let i++                 //每次循环i+1   

done
echo "$sum                       //打印结果 $sum


二、Shell函数

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

1、函数基本格式

[function] 函数名(){
  命令序列
[return x]                           #使用return或exit可以显示的结束函数 
}

或者

                                     #也可以省略掉[function],它表示该函数的功能

函数名() {                            #函数名后面()是没有内容的
  命令序列                            #我们执行的命令内容放在{}里面
}


 

  • 函数定义完之后并不会自动执行,需要调用才行

  • 好处在于可以写一段功能代码作为函数,有需要就直接调用定义的时候哪怕出现语法错误也没关系,不调用就不会报错

  • 当然我们写函数最终目的还是为了调用,为了实现某个功能块。

2、函数返回值

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

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

返回值范围

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

[root@zhang hanshu]#sh retun.sh 
请输入数字:3
6
[root@zhang hanshu]#sh retun.sh 
请输入数字:127
254
[root@zhang hanshu]#sh retun.sh 
请输入数字:128
0


3、函数的作用范围

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

local一般用于局部变量声明,多在在函数内部使用。

  1. shell脚本中定义的变量是global的,其作用域从被定义的地方开始,到shell结束或被显示删除的地方为止。
  2. shell函数定义的变量默认是global的,其作用域从“函数被调用时执行变量定义的地方”开始,到shell结束或被显示删除处为止。函数定义的变量可以被显示定义成local的,其作用域局限于函数内。但请注意,函数的参数是local的。
  3. 如果同名,Shell函数定义的local变量会屏蔽脚本定义的global变量。

4、函数的参数
参数的用法

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



参数的表示方法

$1 $2 $3 ......${10} ${11}......


4.1 传参计算两个数的和


4.2 调用函数删除文件


4.3 用return返回值

 

5、递归函数
调用自己本身的函数

5.1 递归遍历目录


5.2 阶乘
**plan 1:**计算特定数的阶乘

**plan 2:**以递归方式计算随机数的阶乘

三、Shell数组

1、定义数组

可以在单行中使用数值列表来定义一个数组

array_var=(test1 test2 test3 test4)
#这些值将会存储在以0为起始索引的连续位置上
或者
#将数组定义为一组“索引—值”
array_var[0]="test1"
array_var[1]="test2"
array_var[2]="test3"
array_var[3]="test4"


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

num=([0]=55 [1]=66 [2]=77 [4]=88)
数组名=([0]=value [1]=value [2]=value. . .)


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

list="11 12 13 14"
num=($list)


2、获取数组长度

${#arr}显示字符串长度

以列表形式打印出数组中的所有值
在数组中,@和*的效果一样

数组元素的遍历


3、元素切片

[root@zhang ~]# arrr=(10 20 30 40 50)
[root@zhang ~]# echo ${arr[*]}
10 20 30 40 50
[root@zhang ~]# echo ${arr[*]:2:3}      #提取出第2个数后面的3个值
30 40 50
[root@zhang ~]# echo ${arr[*]:1:3}       #提取出第1个数后面的3个值
20 30 40
[root@zhang ~]# echo ${arr[*]:0:4}         #提取出第0个数后面的4个值
10 20 30 40


4、元素替换

[root@zhang ~]# arr=(1 3 5 7 9)
[root@zhang ~]# echo ${arr[*]}
1 3 5 7 9
[root@zhang ~]# echo ${arr[*]/3/88}     #3指的是查找数组里面的字符,88指的是需要替换的字符
1 88 5 7 9
[root@zhang ~]# echo ${arr[*]/9/100}
1 3 5 7 100


5、元素删除

[root@zhang ~]# arr=(2 4 6 8 10)
[root@zhang ~]# echo ${arr[*]}
2 4 6 8 10
[root@zhang ~]# unset arr[2]   #删除下标为2的值,即索引为2的值
[root@zhang ~]# echo ${arr[*]}
2 4 8 10
[root@zhang ~]# unset arr[4]
[root@zhang ~]# echo ${arr[*]}
2 4 8


6、冒泡排序

数组排序算法:冒泡排序
类似气泡上涌的动作,会将数据在数组中从小到大或者从大到小不断的向前移动。

基本思想:
冒泡排序的基本思想是对比相邻的两个元素值,如果满足条件就交换元素值,把较小的元素移动到数组前面,把大的元素移动到数组后面(也就是交换两个元素的位置),这样较小的元素就像气泡一样从底部上升到顶部。

算法思路:
冒泡算法由双层循环实现,其中外部循环用于控制排序轮数,一般为要排序的数组长度减1次,因为最后一次循环只剩下一个数组元素,不需要对比,同时数组已经完成排序了。而内部循环主要用于对比数组中每个相邻元素的大小,以确定是否交换位置,对比和交换次数随排序轮数而减少。
举例:

#!/bin/bash
array=(98 76 24 100 35 3)
echo "old_array:${array[*]}"
lt=${#array[*]}
#定义比较轮数,比较轮数为数组长度-1,从1开始
for ((i=1;i<$lt;i++))
do
  #确定比较元素的位置,比较相邻两个元素,较大的数往后放,比较次数随比较轮数而
减少
  for ((j=0;j<$lt-i;j++))
  do
    #定义第一个元素的值
    first=${array[$j]}
    #定义第二个元素的值
    k=$[$j+1]
    second=${array[$k]}
    #如果第一个元素比第二个元素大,就互换
    if [ $first -gt $second ];then
    #把第一个元素的值保存到临时变量中
    temp=$first
    #把第二个元素值赋给第一个元素
     array[$j]=$second
    #把临时变量赋给第二个元素
     array[$k]=$temp
    fi
    done
done
echo "new_array:${array[@]}"

四、总结

本文主要讲了三种循环语句和Shell函数的定义方法以及数组的使用方法。

for语句可根据已知的列表对象重复执行命令序列,更适合无规律的循环操作。
while语句可根据特定的条件重复执行命令序列,更适合有规律的循环操作。
until语句重复测试某个条件,只要条件不成立则反复执行。
Shell函数的调用
Shell数组的使用方法
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值