shell编程之循环语句与函数

7 篇文章 0 订阅
本文详细介绍了Shell编程中的循环语句,包括for、while和until,通过实例讲解了各自的应用。此外,还深入探讨了Shell函数的定义、作用范围、参数传递及递归函数的使用。最后,提到了Shell数组的运用以及脚本调试的方法,帮助读者更好地理解和应用Shell编程。
摘要由CSDN通过智能技术生成

一 循环语句

1.1 for循环语句的结构

  • 读取不同的变量值,用来逐个执行同一组命令
    请添加图片描述

示例1

  • 批量添加用户
    用户名存放在users。txt文件中,每行一个
    初始密码均为123456
    验证脚本
[root@localhost ~]# vi /root/users.txt
chen
wen
jian
[root@localhost ~]# vi 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 +x uaddfor.sh 
[root@localhost ~]# ./uaddfor.sh 
[root@localhost ~]# tail -3 /etc/passwd 
chen:x:1001:1001::/home/chen:/bin/bash
wen:x:1002:1002::/home/wen:/bin/bash
jian:x:1003:1003::/home/jian:/bin/bash

示例2

  • 根据ip地址检查主机状态
    IP地址存放在ipadds.txt文件中,每行一个
    使用ping命令检测个主机的连通性
[root@localhost ~]# vi /root/ipadds.txt
20.0.0.1
20.0.0.2
20.0.0.10
20.0.0.21
20.0.0.100
[root@localhost ~]# vi 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" && echo "Host $IP is up" >>/root/ipup.txt
  else
    echo "Host $IP is down" && echo "Host $IP is down" >>/root/ipdown.txt
  fi
done
[root@localhost ~]# chmod +x chkhosts.sh 
[root@localhost ~]# ./chkhosts.sh 
Host 20.0.0.1 is up
Host 20.0.0.2 is up
Host 20.0.0.10 is down
Host 20.0.0.21 is up
Host 20.0.0.100 is down
[root@localhost ~]# ll
......
-rw-r--r--  1 root root   49 Aug 13 09:17 ipadds.txt
-rw-r--r--  1 root root  196 Aug 13 09:19 ipdown.txt
-rw-r--r--  1 root root  224 Aug 13 09:19 ipup.txt
......
[root@localhost ~]# cat ipup.txt 
Host 20.0.0.1 is up
Host 20.0.0.2 is up
Host 20.0.0.21 is up
[root@localhost ~]# cat ipdown.txt 
Host 20.0.0.10 is down
Host 20.0.0.100 is down

1.2 while语句的结构

  • 重复测试某个条件,只要条件成立则反复执行
    请添加图片描述

示例1

  • 批量添加用户
    用户名以stu开头,按数字顺序进行编号
    一共添加20个用户,即stu1、stu2…stu20
    初始密码均为123456
[root@localhost ~]# vi usaddwhile.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 +x usaddwhile.sh 
[root@localhost ~]# ./usaddwhile.sh 
[root@localhost ~]# grep "stu" /etc/passwd
stu1:x:1001:1001::/home/stu1:/bin/bash
stu2:x:1002:1002::/home/stu2:/bin/bash
stu3:x:1003:1003::/home/stu3:/bin/bash
stu4:x:1004:1004::/home/stu4:/bin/bash
stu5:x:1005:1005::/home/stu5:/bin/bash
stu6:x:1006:1006::/home/stu6:/bin/bash
stu7:x:1007:1007::/home/stu7:/bin/bash
stu8:x:1008:1008::/home/stu8:/bin/bash
stu9:x:1009:1009::/home/stu9:/bin/bash
stu10:x:1010:1010::/home/stu10:/bin/bash
stu11:x:1011:1011::/home/stu11:/bin/bash
stu12:x:1012:1012::/home/stu12:/bin/bash
stu13:x:1013:1013::/home/stu13:/bin/bash
stu14:x:1014:1014::/home/stu14:/bin/bash
stu15:x:1015:1015::/home/stu15:/bin/bash
stu16:x:1016:1016::/home/stu16:/bin/bash
stu17:x:1017:1017::/home/stu17:/bin/bash
stu18:x:1018:1018::/home/stu18:/bin/bash
stu19:x:1019:1019::/home/stu19:/bin/bash
stu20:x:1020:1020::/home/stu20:/bin/bash

示例2

  • 猜商品价格游戏
    通过变量RANDOM获得随机数
    提示用户猜测并记录次数,猜中后退出循环
[root@localhost ~]# vi 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 +x pricegame.sh

1.3 until循环语句

  • 重复测试某个条件,只要条件不曾李则反复执行
    请添加图片描述

实例1

  • 计算1~50的和值
    通过循环累加的方式计算1~50的和值
[root@localhost ~]# vi sum1to50.sh
#!/bin/bash
i=0
s=0
until [ $i -ge 50 ]
do
  let "i=$i+1"
  let "s=$s+$i"
done
  echo "1加到50的和为:" $s 
[root@localhost ~]# chmod +x sum1to50.sh 
[root@localhost ~]# ./sum1to50.sh 
1加到50的和为: 1275

shell函数

2.1 shell函数

  • 将命令序列按格式写在一起
  • 可方便重复使用命令序列
  • Shell函数定义
#使用return或exit可以显示的结束函数
[ function 函数名(){
         命令序列
           [return x]
 }
  • 调用函数的方法
函数名 [参数1] [参数2]

实例

  • 两个数字求和
    通过sum() {}定义函数
    使用read命令交互输入两个数并求和
[root@localhost ~]# vi sum.sh
#!/bin/bash
sum(){
  read -p "请输入第一个数:" NUM1
  read -p "请输入第二个数:" NUM2
  echo "你输入的两个数为:" $NUM1$NUM2
  SUM=$((NUM1 + NUM2))
  echo "两个数的和为: $SUM"
}
sum
[root@localhost ~]# ./sum.sh 
请输入第一个数:10
请输入第二个数:20
你输入的两个数为: 10和20
两个数的和为: 30

2.2 函数的作用范围

  • 函数在Shell脚步中仅在当前Shell环境中有效

  • Shell脚本中变量默认全局有效

  • 讲变量限定在函数内部使用local命令

  • 示例

      1. 函数内部变量通过local来实现
      2. 通过定义myfun函数,在其内部设置举报变量
      3. 函数内部和外部分别赋值,进行结束验证
    
[root@localhost ~]# vi 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 
8
9

2.3 函数的参数

  • 参数的用法
函数名称 参数1 参数2 参数3 ......
  • 参数的表示方法
    $1 $2 $3 … ${10} ${11}…

实例

  • 通过函数参数将日志信息写入文件
    通过定义appendfile函数实现
[root@localhost ~]# vi write_log.sh

#!/bin/bash
mydir="/data"
outfile="${mydir}/my.log"
[ -e "${mydir}" ] || mkdir -p ${mydir}
appendfile()
{
  echo "$2" >> "$1"
}
appendfile ${outfile} "first line content"
appendfile ${outfile} "second line content"
[root@localhost ~]# chmod +x write_log.sh 
[root@localhost ~]# ./write_log.sh 
[root@localhost ~]# cat /data/my.log 
first line content
second line content

2.4 递归函数

  • 调用自己本身的函数

实例

  • 递归遍历目录
    通过定义递归函数list_files来实现
[root@localhost ~]# vi fun_recursion.sh
function list_files()
{
  for f in `ls $1`;
  do
    if [ -d "$1/$f" ];
    then
      echo "$2$f"
      list_files "$1/$f" "  $2"
    else
      echo "$2$f"
    fi
  done
}
list_files "/var/log" ""
[root@localhost ~]# chmod +x fun_
fun_recursion.sh  fun_scope.sh      
[root@localhost ~]# chmod +x fun_recursion.sh 
[root@localhost ~]# ./fun_recursion.sh 
anaconda
  anaconda.log
  ifcfg.log
  journal.log
  ks-script-9EcVF8.log
  packaging.log
  program.log
  storage.log
......

三 Shell数组

3.1 Shell数组

  • 应用场景包括
    获取数组长度
    获取元素长度
    遍历元素
    元素切片
    元素替换
    元素删除

  • 数组定义方法

#方法一
数组名=(value0 value1 value2 ...)
#方法二
数组名=([0]=value [1]=value [2]=value ...)
#方法三
列表名="value0 value1 value2 ..."
数组名=($列表名)
  • 数组包括的数据类型
    ·数值类型
    ·字符类型
    ----使用 “ ” 或 ‘ ’ 定义
数组名[0]=“value”
数组名[1]=“value”
数组名[2]=“value”
  1. 获取数组长度
[root@localhost ~]# a=(1 2 3 4 5)
[root@localhost ~]# a=${#a[*]}
[root@localhost ~]# echo $a
5
  1. 读取某下标赋值
[root@localhost ~]# a2=${a[2]}    //第三个元素
[root@localhost ~]# echo $a2
3
  1. 数组遍历
[root@localhost ~]# vi a.sh
#!/bin/bash
a=(1 2 3 4 5)
for v in ${a[*]}
do
  echo $v
done
[root@localhost ~]# chmod +x a
anaconda-ks.cfg  a.sh             
[root@localhost ~]# chmod +x a.sh 
[root@localhost ~]# ./a.sh 
1
2
3
4
5
  1. 数组切片
[root@localhost ~]# a=(1 2 3 4 5)
[root@localhost ~]# echo ${a[*]}       //输出整个数组
1 2 3 4 5
[root@localhost ~]# echo ${a[*]:0:2}      //${数组名[@或*]:起始位置:长度}
1 2
[root@localhost ~]# echo ${a[*]:2:3}
3 4 5
  1. 数组切换
[root@localhost ~]# a=(1 2 3 4 5)
[root@localhost ~]# echo ${a[*]/4/7}    //j将数组a里面的字符4替换成7
1 2 3 7 5
[root@localhost ~]# echo ${a[*]}    //并不会替换数组原有内容
1 2 3 4 5
[root@localhost ~]# a=(${a[*]/4/7})    //实现永久替换
[root@localhost ~]# echo ${a[*]}
1 2 3 7 5
  1. 数组删除
[root@localhost ~]# a=(1 2 3 4 5)
[root@localhost ~]# unset a              //删除数组
[root@localhost ~]# echo ${a[*]}

[root@localhost ~]# a=(1 2 3 4 5)
[root@localhost ~]# unset a[2]           //删除第三个元素
[root@localhost ~]# echo ${a[*]}
1 2 4 5

3.2 Shell脚本调试

在 Shell 脚本开发中,经常碰到一些规范方面的问题,例如忘了使用引号或在 if 语句末尾处忘记加 fi 结束。要注意把复杂的脚本简单化,要思路清晰,并且分段实现。当执行脚本时出现错误后,不要只看那些提示的错误行,而是要观察整个相关的代码段。
为避免编写的脚本出错,除了在编写脚本时注意书写规范,排除语法错误,更重要的是 利用调试脚本工具来调试脚本。echo 命令是最有用的调试脚本工具之一,一般在可能出现问题的脚本中加入 echo 命令,采用的是分段排查的方式。

  • 常用参数的具体含义为:
    -n:不会执行该脚本,仅查询脚本语法是否有问题,如果没有语法问题就不显示任 何内容,如果有问题会提示报错。
    -v:在执行脚本时,先将脚本的内容输出到屏幕上然后执行脚本,如果有错误,也 会给出错误提示。
    -x:将执行的脚本内容输出到屏幕上,这个是对调试很有用的参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值