shell 循环语句和函数

循环语句

  • 一、循环语句
  • 1、for循环详解
  • 2、while语句
  • 3、until语句
  • 4、双for循环
  • 5、break和continue
    • break,我们可以通过内外循环的输出来看break的特性。
    • continue
  • 二、函数
  • 1、shell函数定义格式
  • 2、函数返回值
  • 3、函数传参
  • 4、递归(调用自己)
  • 5、函数库
  • 实例

一、循环语句

1、for循环详解

for循环语句允许脚本一次性读取多个信息,然后逐一对信息进行操作处理。当要处理的数据有范围时,
使用for循环语句就再适合不过了。

读取不同的变量值,用来逐个执行同一组命令

语法:
for 变量名 in 取值列表
do
命令序列(命令行)
done

示例1:
下面使用for循环语句从列表文件中读取多个用户,然后为其逐一创建用户账户并设置密码。
首先创建用户名称的列表文件users.txt,每个用户名称单独一行。
vim /root/users.txt
jim
bob
marry
rose
mike

接下来编写shell标本addusers.sh。在脚本中使用read命令读取用户输入的密码值,然后赋值给PASSWD
变量,并通过-p参数向用户显示一段提示信息,告诉用户正在输入的内容即将作为账户密码。

vim  /root/addusers.sh
#!/bin/bash
read -p "enter the user password:" PASSWD
for UNAME in `cat /root/users.txt`
do
        useradd $UNAME
        echo "$PASSWD" | passwd --stdin $UNAME
        echo "$UNAME",create success
done

示例2:
循环输出1-10

#!/bin/bash
for ((i=1;i<=10;i++))               //自增1
do
        echo $i
done


for ((i=1;i<=10;i+=2))               //自增2

示例3:
用for语句,输出1-100的所有整数和

#!/bin/bash
a=0                                  //先定义一个和的变量
for ((i=1;i<=100;i++))
do
        a=$(($a+$i))          //循环赋值(1+..+100)的和给a
done
echo "1-100所有整数相加的和未$a"

示例4:
根据IP地址检测主机状态
主机列表
vim /root/iplist
192.168.100.10
192.168.100.20
192.168.100.30

vim  b.sh
#!/bin/bash
ip=$(cat /root/iplist.txt)
for i in $ip
do
ping -c 3 $i &>/dev/null
if [ $? -eq 0 ];then
        echo "$i通"
else
        echo "$i不通"
fi
done

2、while语句

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

示例1:
显示0-10的所有整数

#!/bin/bash
a=0
while [ $a -le 10 ]
do
        echo $a
        let a++
done

示例2:
求1-100的整数和

#!/bin/bash
i=0
n=1
while [ $n -le 100 ]
do
i=$(( $i + $n ))
let n++
done
echo "1-100的和为:$i"

随机数

[root@rhel8 ~]# expr 555 % 1000
555
[root@rhel8 ~]# expr $RANDOM % 100
42
[root@rhel8 ~]# expr $RANDOM % 100
9
[root@rhel8 ~]# expr $RANDOM % 100
53
[root@rhel8 ~]# expr $RANDOM % 1000
985
[root@rhel8 ~]# expr $RANDOM % 1000
639

示例3:
随机猜数字游戏,1000以内的猜数字游戏

#!/bin/bash
num=$(expr $RANDOM % 1000)
a=0
echo "数字范围为0-999的整数,猜猜看"
while true
do
read -p "请输入你猜的整数:" n
let a++
if [ $n -eq $num ];then
	echo "恭喜你答对了,数字为$num"
	echo "你总共猜了$a次"
	exit 0
elif [ $n -gt $num ];then
	echo "你猜高了"
else
	echo "你猜低了"
fi
done

3、until语句

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

示例1:
练习
求1-100的整数和

4、双for循环

即在一个for循环内部再加一个for循环

#!/bin/bash
for ((a=1;a<=5;a++))
do
        echo "a=$a"
        for ((b=1;b<=5;b++))
        do
                echo "b=$b"
        done
done

5、break和continue

在内循环执行break 就跳出当前的内循环了,去执行外循环了
作用:
1跳出当前循环
2并且break下面的语句不去执行

break,我们可以通过内外循环的输出来看break的特性。

#!/bin/bash
#break
for(( a=1;a<=5; a++ ))
do
  echo "outside $a"
  for ((b=1;b<=5;b++ ))
  do
     if [ $b -eq 4 ]
      then
      break                   #这里当b=4的时候,进行break,不进行后面的输出$b.
     fi
   echo "inside $b "
  done

done

[root@rhel8 ~]# ./d.sh 
outside 1
inside 1
inside 2
inside 3
outside 2
inside 1
inside 2
inside 3
outside 3
inside 1
inside 2
inside 3
outside 4
inside 1
inside 2
inside 3
outside 5
inside 1
inside 2
inside 3

内循环到4就停止了,5就不去判断了

continue

中止某次循环,不会完全终止整个命令

#!/bin/bash
#continue
for (( a=1;a<=15;a++))
do
    if [ $a -gt 5 ] && [ $a -lt 10 ]
    then
       continue
    fi
   echo " $a "
done

[root@rhel8 ~]# ./e.sh
1
2
3
4
5
10
11
12
13
14
15


二、函数

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

1、shell函数定义格式


function 函数名{ 

   命令序列
   
 }


  函数名(){ 
  
    命令序列
    
  }

2、函数返回值

return
return 表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值(0-255)
原则:
1.函数已结束就取返回值,因为 $? 只是对最后一条命令进行判断
2.0-255,超出时 除以256取余
echo也能直接返回

测试案例

#!/bin/bash
#测试
function hehe {
        read -p "请输入任意一个整数值:" n
        return $[$n*2]
}

hehe
echo "$?"

[root@rhel8 ~]# ./aa.sh 
请输入任意一个整数值:40
80
[root@rhel8 ~]# ./aa.sh 
请输入任意一个整数值:250
244
[root@rhel8 ~]# ./aa.sh 
请输入任意一个整数值:256
0

3、函数传参

函数变量的作用范围(局部变量以及全局变量)
函数在shell脚本中仅在当前shell环境中有效
shell脚本中变量默认全局有效
将变量限定一个函数的内部local,即局部变量


(1)传参
[root@rhel8 opt]#vim bb.sh
#!/bin/bash
sum1 () {
        sum=$[ $1 + $2 ]
        echo $sum
}
sum1 $1 $2

[root@rhel8 ~]# ./bb.sh 20 30
50
[root@rhel8 ~]# ./bb.sh 1 6
7

(2)变量的局部与全局
将变量限定在函数内部使用local命令
即这个local的变量仅仅在当前的函数内有效,在别的函数中无效。

#!/bin/bash
abc () {
        echo "函数内的未经过local的变量i值$i"
        local i
        i=6
        echo "函数内的变量i值是$i"
}
i=9
abc
echo "函数外面的变量i值是$i"

[root@rhel8 ~]# ./cc.sh
函数内的未经过local的变量i值9
函数内的变量i值是6
函数外面的变量i值是9

(3)local的进击

#!/bin/bash
abc () {
        echo "inside1 $i"
        let i++
        local i
        i=8
        echo "inside2 $i"
}
i=9
abc
echo "outside $i"

[root@rhel8 ~]# ./cc.sh 
inside1 9
inside2 8
outside 10

4、递归(调用自己)

#!/bin/bash
function hehe() {
        if [ $1 -eq 1 ];then
                echo 1
        else
                local temp=$[ $1 - 1 ]
                local result=`cy $temp`
                echo $[ result * $1 ]
        fi
}
read -p "输入一个值:" vaule
result=`hehe $vaule`
echo "阶乘的值为: $result"

[root@rhel8 ~]# ./dd.sh 
输入一个值:5
阶乘的值为: 120
[root@rhel8 ~]# ./dd.sh 
输入一个值:3
阶乘的值为: 6

5、函数库

就是把一般脚本的主体执行代码和定义函数部分相互分离,把定义的函数部分集中放在同一个脚本中。
具体执行的时候,只需要直接进行调用函数集合的脚本文件即可。

这里我把加减乘除共4个函数,做了一个函数库。

[root@rhel8 ~]# cat ee.sh 
#!/bin/bash
#ee.sh函数库
jia() { 
	result=$[ $1 + $2 ]
	echo "$result"
}

jian() { 
	result=$[ $1 - $2 ]
	echo "$result"
}

cheng() { 
	result=$[ $1 * $2 ]
	echo "$result"
}

chu() {
	if [ $2 -ne 0 ];then
	result=$[ $1 / $2 ]
	echo "$result"
	else
	echo "除法中分母不能为0"
	fi
}



[root@rhel8 ~]# cat ff.sh 
#!/bin/bash
. /root/ee.sh

read -p "请输入第一个数字:" n
read -p "请输入第二个数字:" m

result1=`jia $n $m`
result2=`jian $n $m`
result3=`cheng $n $m`
result4=`chu $n $m`

echo "两数之和为: $result1"
echo "两数之差为: $result2"
echo "两数之积为: $result3"
echo "两数之商为: $result4"

[root@rhel8 ~]# chmod +x ff.sh 
[root@rhel8 ~]# ./ff.sh 
请输入第一个数字:5 
请输入第二个数字:2
两数之和为: 7
两数之差为: 3
两数之积为: 10
两数之商为: 2

实例

1、创建脚本xx.sh,使用for循环,输出九九乘法表,提示:echo -n 不要在最后自动换行
第一种方法

[root@sb ~]# vim hehe.sh 
#!/bin/bash
n=1
while [ $n -le 9 ]
do
        for ((i=1;i<=9;i++))
        do
        [ $i -le $n ] && echo -n "$n*$i=$(($n*$i)) "
        done
        let n++
        echo ""
done
[root@sb ~]# chmod +x hehe.sh
[root@sb ~]# ./hehe.sh 
1*1=1 
2*1=2 2*2=4 
3*1=3 3*2=6 3*3=9 
4*1=4 4*2=8 4*3=12 4*4=16 
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 

第二种方法

[root@sb ~]# vim hehe.sh 

#!/bin/bash
for ((n=1;n<=9;n++))
do
        for ((i=1;i<=9;i++))
        do
        [ $i -le $n ] && echo -n "$n*$i=$(($n*$i)) "
        done
        echo ""
done
[root@sb ~]# ./hehe.sh 
1*1=1 
2*1=2 2*2=4 
3*1=3 3*2=6 3*3=9 
4*1=4 4*2=8 4*3=12 4*4=16 
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 

2、创建脚本xx.sh,使用until求1-100整数和

[root@sb ~]# vim hehe.sh 
#!/bin/bash
i=1
n=0
until [ $i -gt 100 ]
do
n=$(( $i + $n ))
let i++
done
echo "1-100的和为:$n"
[root@sb ~]# ./hehe.sh 
1-100的和为:5050

3、写一个脚本,要求如下
(1)设定变量xx的值为/etc/passwd
(2)依次向/etc/passwd中的每个用户问好,并且说出对方的ID是什么。结果输出如下:
Hello,root,your UID is 0.
(3)统计当前系统一共有多少个用户

[root@sb ~]# vim hehe.sh 
#!/bin/bash
sb="/etc/passwd"
hehe=` wc -l $sb | cut -d" " -f1`
for i in `seq 1 $hehe`
do
           user=`head -$i $sb|tail -1 | cut -d: -f1`
           userid=`head -$i $sb|tail -1 | cut -d: -f3`
           echo "Hello,$user,your UID $userid"
done
           echo "用户有: $hehe"
[root@sb ~]# chmod +x hehe.sh         
[root@sb ~]# ./hehe.sh 
[root@sb ~]# ./hehe.sh 
Hello,root,your UID 0
Hello,bin,your UID 1
Hello,daemon,your UID 2
Hello,adm,your UID 3
Hello,lp,your UID 4
Hello,sync,your UID 5
Hello,shutdown,your UID 6
Hello,halt,your UID 7
Hello,mail,your UID 8
Hello,operator,your UID 11
Hello,games,your UID 12
Hello,ftp,your UID 14
Hello,nobody,your UID 65534
Hello,dbus,your UID 81
Hello,systemd-coredump,your UID 999
Hello,systemd-resolve,your UID 193
Hello,tss,your UID 59
Hello,polkitd,your UID 998
Hello,unbound,your UID 997
Hello,geoclue,your UID 996
Hello,rtkit,your UID 172
Hello,pipewire,your UID 995
Hello,pulse,your UID 171
Hello,qemu,your UID 107
Hello,usbmuxd,your UID 113
Hello,gluster,your UID 994
Hello,rpc,your UID 32
Hello,avahi,your UID 70
Hello,chrony,your UID 993
Hello,saslauth,your UID 992
Hello,libstoragemgmt,your UID 991
Hello,dnsmasq,your UID 984
Hello,radvd,your UID 75
Hello,sssd,your UID 983
Hello,cockpit-ws,your UID 982
Hello,cockpit-wsinstance,your UID 981
Hello,colord,your UID 980
Hello,rpcuser,your UID 29
Hello,setroubleshoot,your UID 979
Hello,flatpak,your UID 978
Hello,gdm,your UID 42
Hello,clevis,your UID 977
Hello,gnome-initial-setup,your UID 976
Hello,sshd,your UID 74
Hello,tcpdump,your UID 72
Hello,haha,your UID 1000
Hello,apache,your UID 48
用户有: 47

4、编写一个脚本,使用函数测试主机192.168.40.10-192.168.40.20主机是否在线,函数名称为
name

[root@sb ~]# vim hehe.sh
#!/bin/bash
haha() {
ping -c 1 -w 1 "1 &> /dev/null
}
for i in {10..20}
do
 if haha 192.168.40.$i;then
        echo "192.168.40.$i通"
else
        echo "192.168.40.$i不通"
fi
done

[root@sb ~]# ./hehe.sh 
192.168.40.10不通
192.168.40.11不通
192.168.40.12不通
192.168.40.13不通
192.168.40.14不通
192.168.40.15不通
192.168.40.16不通
192.168.40.17不通
192.168.40.18不通
192.168.40.19不通
192.168.40.20不通
[root@sb ~]# 

你可能感兴趣的:(linux,服务器,运维)