理论+实验 详解Shell编程之循环语句与函数

一 循环语句

1.1 for循环语句

在这里插入图片描述

[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
[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循环语句

在这里插入图片描述

[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
[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循环语句

在这里插入图片描述

[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函数

[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
[root@localhost ~]# vi function
servicectl_usage(){
  echo "Usage:servicectl<service-name><start|stop|restart|reload|status>"
  return 1
}

chk_centos_ver(){
  grep "CentOS.*release 7." /etc/centos-release &>/dev/null && echo "7"
  grep "CentOS.*release 6." /etc/centos-release &>/dev/null && echo "6"
  grep "CentOS.*release 5." /etc/centos-release &>/dev/null && echo "5"
}

servicectl(){
  [[ -z $1 || -z $2 ]] && servicectl_usage
  [ $(chk_centos_ver)=="7" ] && systemctl $2 ${1}.service || service $1 $2
}
[root@localhost ~]# chmod +x function 
[root@localhost ~]# source function 
[root@localhost ~]# echo 'source /root/function' >> ~/.bashrc
[root@localhost ~]# servicectl vsftpd status

2.2 函数的作用范围

[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 函数的参数

[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 递归函数

[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数组

(1)获取数组长度

[root@localhost ~]# a=(1 2 3 4 5)
[root@localhost ~]# a=${#a[*]}
[root@localhost ~]# echo $a
5

(2)读取某下标赋值

[root@localhost ~]# a2=${a[2]}    //第三个元素
[root@localhost ~]# echo $a2
3

(3)数组遍历

[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

(4)数组切片

[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

(5)数组切换

[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

(6)数组删除

[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:将执行的脚本内容输出到屏幕上,这个是对调试很有用的参数。

#!/bin/bash
set -x	//开启调试模式
read -p "请输入您的分数(0-100):" GRADE
if [ $GRADE -ge 85 ] && [ $GRADE -le 100 ]  then
echo "$GRADE 分!优秀"
set +x	//关闭调试模式
elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ]  then


else fi

echo "$GRADE 分,合格"

echo "$GRADE 分?不合格"
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值