shell编程之循环语句与函数

一:for循环语句

1:for循环语句的结构

for 变量名 in 取值列表

do

命令序列

done

注意:for循环语句需要有一个取值列表

备注:

for 语句的执行流程:首先将列表中的第一个取值赋给变量,并执行 do…done 循环体

中的命令序列;然后将列表中的第二个取值赋给变量,并执行循环体中的命令序列……依此

类推,直到列表中的所有取值用完,最后将跳至 done 语句,表示结束循环

2:案例 根据姓名列表批量添加用户

(1)创建用户的列表文件

[root@localhost ~]# vim /root/users.txt

zhangsan

lisi

wangwu

(2)编辑批量添加用户的脚本

[root@localhost ~]# vim uaddfor.sh

#!/bin/bash

ULIST=$(cat /root/users.txt)

for UNAME in $ULIST

do

   useradd $UNAME

   echo "123456" | passwd --stdin $UNAME &>/dev/null

done

给脚本赋予执行权限

[root@localhost ~]# chmod 755 uaddfor.sh

测试并确认执行结果

[root@localhost ~]#./uaddfor.sh

[root@localhost ~]# tail -3 /etc/passwd

(3)编辑批量删除用户的脚本

[root@localhost ~]# vim udelfor.sh

#!/bin/bash

ULIST=$(cat /root/users.txt)

for UNAME in $ULIST

do

   userdel -r $UNAME &>/dev/null

   

done

给脚本赋予执行权限

[root@localhost ~]# chmod a+x udelfor.sh

测试并确认执行结果

[root@localhost ~]#./udelfor.sh

[root@localhost ~]# id zhangsan

3:案例  根据 IP 地址列表检查主机状态

1)创建IP地址列表文件

[root@localhost ~]# vim /root/ipadds.txt

172.16.1.1

172.16.1.111

172.16.1.222

192.168.10.10

2)编辑循环检查各主机的脚本

[root@localhost ~]# vim chkhosts.sh

#!/bin/bash

HLIST=$(cat /root/ipadds.txt)

for IP in $HLIST

do

   ping -c 3 -i 0.2 -W 3 $IP &> /dev/null

   if [ $? -eq 0  ]

   then

      echo "Host $IP is up."

   else

      echo "Host $IP is down."

   fi

done

[root@localhost ~]# chmod a+x chkhost.sh

测试并确认执行结果

[root@localhost ~]#./chkhosts.sh

二:使用 while 循环语句

1:while语句的语法结构

while 条件测试操作

do

命令序列

done

备注:

while 语句的执行流程:首先判断 while 后的条件测试操作结果,如果条件成立,则执

do…done 循环体中的命令序列;返回 while 后再次判断条件测试结果,如果条件仍然成

立,则继续执行循环体;再次返回到 while 后,判断条件测试结果……如此循环,直到 while

后的条件测试结果不再成立为止,最后跳转到 done 语句,表示结束循环

2:案例  批量添加规律编号的用户

1)批量添加用户脚本

[root@localhost ~]# vim uaddwhile.sh

#!/bin/bash

PREFIX="stu"

i=1

while [ $i -le 20 ]

do

    useradd ${PREFIX}$i

    echo "123456" | passwd --stdin ${PREFIX}$i &> /dev/null

    let i++

done

[root@localhost ~]# chmod a+x uaddwhile.sh

测试并确认执行结果

[root@localhost ~]#./uaddwhile.sh

[root@localhost ~]# grep "stu" /etc/passwd | tail -3

或者

#!/bin/bash

PREFIX="stu"

i=1

while [ $i -le 20 ]

do

    useradd ${PREFIX}$i

    echo "123456" | passwd --stdin ${PREFIX}$i &> /dev/null

    i=`expr $i + 1`

done

[root@localhost ~]# chmod a+x uaddwhile.sh

测试并确认执行结果

[root@localhost ~]#./uaddwhile.sh

[root@localhost ~]# grep "stu" /etc/passwd | tail -3

2)批量删除用户脚本

[root@localhost ~]# vim udelwhile.sh

#!/bin/bash

PREFIX="stu"

i=1

while [ $i -le 20 ]

do

     userdel -r ${PREFIX}$i

     let i++

done

[root@localhost ~]# chmod a+x udelwhile.sh

测试并确认执行结果

[root@localhost ~]#./udelwhile.sh

id stu20

3:案例  猜价格游戏

[root@localhost ~]# vim pricegame.sh

#!/bin/bash

PRICE=$(expr $RANDOM % 1000)

TIMES=0

echo "商品实际价格范围为0-999,猜猜看是多少?"

while true

do

    read -p "请输入你猜测的价格数目:" INT

    let TIMES++

    if [ $INT -eq $PRICE ] ; then

        echo "恭喜你答对了,实际价格是 $PRICE"

        echo "你总共猜测了$TIMES 次"

        exit 0

    elif [ $INT -gt $PRICE  ] ; then

        echo "太高了!"

    else

        echo "太低了!"

    fi

done

[root@localhost ~]# chmod a+x pricegame.sh

注意:linux中随机数的取值范围是0--32767,和什么数取余,取余后的最大数就是谁,不包含该数字

测试并确认执行结果

[root@localhost ~]#./pricegame.sh

商品实际价格范围为0-999,猜猜看是多少?

请输入你猜测的价格数目:500

太高了!

......

三:until 循环语句

1:until 语句的结构

until 条件测试操作

do

done

备注:

until 语句的执行流程:首先判断 until 后的条件测试操作结果,如果条件不成立,则执

do…done 循环体中的命令序列;返回 until 后再次判断条件测试结果,如果条件仍然不

成立,则继续执行循环体;再次返回到 until 后,判断条件测试结果……如此循环,直到 until

后的条件测试结果成立为止,最后跳转到 done 语句

直到条件满足后才会停止循环

2:until语法案例

(1)案例一

[root@localhost ~]# vim until_v1.sh

#!/bin/bash

i=0;s=0

until [ $i -eq 50 ]

do

let "i=$i+1";let "s=$s+$i"

done

echo 'sum(1..50)='$s

[root@localhost ~]# chmod +x sum1to50_until_v1.sh

[root@localhost ~]# ./sum1to50_until_v1.sh

sum(1..50)=1275

(1)案例二

[root@localhost ~]# vim until_v2.sh

var1=100

until [ $var1 -eq 0 ]

do

        echo $var1

        var1=$[ $var1 - 25 ]

done

[root@localhost ~]# chmod +x until_v2.sh

[root@localhost ~]# ./until_v2.sh

四:Shell 函数

Shell 函数可用于存放一系列的指令。在 Shell 脚本执行的过程中,函数被置于内存中,

每次调用函数时不需要从硬盘读取,因此运行的速度比较快。在 Shell 编程中函数并非是必

须的元素,但使用函数可以对程序进行更好的组织。将一些相对独立的代码变成函数,可以

提高程序可读性与重用性,避免编写大量重复代码。

1:函数的用法

[function] 函数名() {

[return x]

}

  • “function”关键字表示定义一个函数,可以省略;
  • “{”符号表示函数执行命令的入口,该符号可以与函数名同行也可以在函数名下一行的句首;
  • “}”符号表示函数体结束,两个大括号之间{ }是函数体;
  • “命令序列”部分可以是任意的 Shell 命令,也可以调用其他函数;
  • “return”表示退出函数返回一个退出值,通过返回值判断执行是否成功,也可以使用 exit 终止整个 Shell 脚本。

2:案例  一个简单的函数脚本

[root@localhost ~]# vim exa1.sh

#!/bin/bash

zhangsan() {

echo "my name is zhangsan"

}

lisi() {

echo "my name is lisi"

}

zhangsan

lisi

[root@localhost ~]# sh exa1.sh

3:案例  带有参数的shell函数示例

[root@localhost ~]#vim exa2.sh

#!/bin/bash

name() {

echo "my name is $1"

}

name $1

[root@localhost ~]# sh exa2.sh zhangsan

my name is zhangsan

[root@localhost ~]# sh exa2.sh lisi

my name is lisi

4:案例 函数变量的作用范围

[root@localhost ~]# vim fun_scope.sh

myfun ()

{

local i

i=8

echo $i

}

i=9

myfun

echo $i

[root@localhost ~]# chmod +x fun_scope.sh

[root@localhost ~]# ./fun_scope.sh

备注:

通过内置命令 local 将变量的值限定在函数内部

五:Shell 数组

Shell 脚本中,数组是一种常见的数据结构,主要的应用场景包括:获取数组长度、

获取元素长度、遍历元素、元素切片、元素替换、元素删除等等。Shell 中的数组与 Java

CPython 不同,只有一维数组,没有二维数组。

1:定义数组的方法

数组常用定义方法包括以下几种。

方法一:

数组名=

value0 value1 value2 ...

方法二:

数组名=

[0]=value [1]=value [2]=value ...

方法三:

列表名=”value0 value1 value2 ...”

数组名=

$列表名)

方法四:

数组名[0]=”value”

数组名[1]=”value”

数组名[2]=”value”

2:获取数组长度

[root@localhost ~]# arr_number=(1 2 3 4 5)

[root@localhost ~]# arr_length=${#arr_number[*]}

[root@localhost ~]# echo $arr_length

5

[root@localhost ~]# arr_length_1=${#arr_number[@]}

[root@localhost ~]# echo $arr_length_1

5

备注:

$* 和 $@ 都表示传递给函数或脚本的所有参数,我们已在《Shell特殊变量》一节中进行了演示,本节重点说一下它们之间的区别。

当 $* 和 $@ 不被双引号" "包围时,它们之间没有任何区别,都是将接收到的每个参数看做一份数据,彼此之间以空格来分隔。

但是当它们被双引号" "包含时,就会有区别了:

"∗ " 会 将 所 有 的 参 数 从 整 体 上 看 做 一 份 数 据 , 而 不 是 把 每 个 参 数 都 看 做 一 份 数 据 。 " *"会将所有的参数从整体上看做一份数据,而不是把每个参数都看做一份数据。 "∗"会将所有的参数从整体上看做一份数据,而不是把每个参数都看做一份数据。

"@"仍然将每个参数都看作一份数据,彼此之间是独立的。

比如传递了 5 个参数,那么对于"∗ " 来 说 , 这 5 个 参 数 会 合 并 到 一 起 形 成 一 份 数 据 , 它 们 之 间 是 无 法 分 割 的 ; 而对于"@"来说,这 5 个参数是相互独立的,它们是 5 份数据。

[root@localhost ~]# vim aa

#!/bin/bash

echo "-- \$* 演示 ---"

for i in "$*"; do

echo $i

done

 

echo "-- \$@ 演示 ---"

for i in "$@"; do

echo $i

done

[root@localhost ~]# bash aa 1 2 3

3:读取某下标赋值

[root@localhost ~]# arr_index2=${arr_number[2]}

[root@localhost ~]# echo ${arr_number[2]}

//第三个元素

[root@localhost ~]# echo $arr_index2

3

echo ${aaa[3]}

4:数组遍历

[root@localhost ~]# vim array_traverse.sh

#!/bin/bash

arr_number=(1 2 3 4 5)

for v in ${arr_number[@]}

do

echo $v

done

[root@localhost ~]# chmod +x array_traverse.sh

[root@localhost ~]# ./array_traverse.sh

1

2

3

4

5

5:数组切片

[root@centos-7 ~]# arr=(1 2 3 4 5)

[root@centos-7 ~]# echo ${arr[@]}

//输出整个数组

1 2 3 4 5

[root@centos-7 ~]# echo ${arr[@]:0:2}

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

1 2

[root@centos-7 ~]# echo ${arr[@]:2:3}

3 4 5

备注:

切片就是输出数组中指定连续的若干位,从第几位开始的往后几个数

6:数组替换

[root@centos-7 ~]# arr=(1 2 3 4 5)

[root@centos-7 ~]# echo ${arr[@]/4/66}

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

1 2 3 66 5

[root@centos-7 ~]# echo ${arr[@]}

//并不会替换数组原有内容

1 2 3 4 5

[root@centos-7 ~]# arr=(${arr[@]/4/66})

//要实现改变原有数组,可通过重新赋值实现

[root@centos-7 ~]# echo ${arr[@]}

1 2 3 66 5

7:数组删除

[root@centos-7 ~]# arr=(1 2 3 4 5)

[root@centos-7 ~]# unset arr

//删除数组

[root@centos-7 ~]# echo ${arr[*]}

[root@centos-7 ~]# arr=(1 2 3 4 5)

[root@centos-7 ~]# unset arr[2]

//删除第三个元素

[root@centos-7 ~]# echo ${arr[*]}

1 2 4 5

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值