一、循环语句

1.1 for循环语句

1.1.1 for语句的结构

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

 

 

1.1.2 for语句应用示例

示例1:
■批量添加用户
●用户名存在user.txt中,每行一个
●初始密码均设为123456
●验证脚本

[root@localhost ~]# vi /root/user.txt
 tom
jack
kitty
[root@localhost ~]# vi uadd.sh 
#!/bin/bash
ULIST=$(cat /root/user.txt)
for UNAME in $ULIST
do
  useradd $UNAME
  echo "123456" | passwd --stdin $UNAME &>/dev/null
done
[root@localhost ~]# chmod +x uadd.sh
[root@localhost ~]# ./uadd.sh
[root@localhost ~]# tail -3 /etc/passwd
tom:x:1001:1001::/home/tom:/bin/bash
jack:x:1002:1002::/home/jack:/bin/bash
kitty:x:1003:1003::/home/kitty:/bin/bash

■若要删除添加的用户,将执行以下命令:

[root@localhost ~]# cp uadd.sh udel.sh
[root@localhost ~]# vi udel.sh 
#!/bin/bash
ULIST=$(cat /root/user.txt)
for UNAME in $ULIST
do
  userdel -r $UNAME
  [ $? = 0 ] && echo "已删除$UNAME"
done
[root@localhost ~]# ./udel.sh 
已删除tom
已删除jack
已删除kitty

示例2:
■根据IP地址检查主机状态
●IP地址存放在ipadds.txt文件中,每行一个
●使用ping命令检测各主机的连通性

[root@localhost ~]# vi /root/ipadds.txt
20.0.0.17
192.168.1.100
20.0.0.1
20.0.0.2
[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 [ $? = 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.17 is down
Host 192.168.1.100 is down
[root@localhost ~]# cat /root/ipup.txt     ##查看up记录##
Host 20.0.0.1 is up
Host 20.0.0.2 is up
[root@localhost ~]# cat /root/ipdown.txt   ##查看down记录##
Host 20.0.0.17 is down
Host 192.168.1.100 is down

1.2 while循环语句

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

 

 


示例1:
■批量添加用户
●用户名称以stu开头,按数字顺序进行编号
●一个添加20个账户,即stu1、stu2、…stu20
●初始密码均设为123456

[root@localhost ~]# vi 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 +x uaddwhile.sh 
[root@localhost ~]# ./uaddwhile.sh 
[root@localhost ~]# tail -20 /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 ~]# cp uaddwhile.sh udelwhile.sh
[root@localhost ~]# vi udelwhile.sh 
#!/bin/bash
PREFIX="stu"
i=1
while [ $i -le 20 ]
do
  userdel -r ${PREFIX}$i
#  echo "123456" | passwd --stdin ${PREFIX}$i &> /dev/null
  let i++
done
[root@localhost ~]# chmod +x udelwhile.sh 
[root@localhost ~]# ./udelwhile.sh 
[root@localhost ~]# tail -2 /etc/passwd
tcpdump:x:72:72::/:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin  ##成功删除##

示例2:
■猜商品价格游戏
●通过变量RANDOM获得随机数
●提示用户猜测并记录次数,猜中后退出循环

[root@localhost ~]# vi price.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 price.sh 
[root@localhost ~]# ./price.sh 
商品实际价格范围为0-999,猜猜看是多少?
请输入你猜测的价格数目:100
太低了!
请输入你猜测的价格数目:555
太低了!
请输入你猜测的价格数目:666
太低了!
请输入你猜测的价格数目:888
太高了!
请输入你猜测的价格数目:777
太低了!
请输入你猜测的价格数目:800
太低了!
请输入你猜测的价格数目:850
太低了!
请输入你猜测的价格数目:880
太高了!
请输入你猜测的价格数目:860
太低了!
请输入你猜测的价格数目:870
太高了!
请输入你猜测的价格数目:865
太低了!
请输入你猜测的价格数目:866
太低了!
请输入你猜测的价格数目:867
太低了!
请输入你猜测的价格数目:868
恭喜你答对了,实际价格是868 echo 您总共猜测了 14 次

1.3 until循环语句

1.3.1 until语句的结构

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

 

 


示例1:
■计算1~50的和值
●通过循环累加的方式计算1~50的和值

[root@localhost ~]# vi sum.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 sum.sh 
[root@localhost ~]# ./sum.sh 
sum(1..50)=1275

■或者可以做以下操作,意义一样

[root@localhost ~]# vi sum.sh
  let i++
#!/bin/bash
i=1;s=0
until [ $i -gt 50 ]
do
  let "s=$s+$i"
  let i++
done
echo 'sum(1..50)='$s
[root@localhost ~]# ./sum.sh 
sum(1..50)=1275

二、 Shell函数

2.1 Shell函数

■将命令序列按格式写在一起
■可方便重复使用命令序列
■Shell函数定义
【 function 】 函数名(){
命令序列
【return x】
}
■调用函数的方法
函数名 【函数1】 【函数2】

2.1 函数应用示例

示例1:
■两个数字求和
●通过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 ~]# chmod +x SUM.sh 
[root@localhost ~]# ./SUM.sh 
请输入第一个数:10
请输入第二个数:20
您输入的两个数为:10和20
两个数的和为:30

或者可以进行以下操作:

[root@localhost ~]# vi SUM.sh
#!/bin/bash
#函数求和
sum(){
 read -p "请输入第一个数:" NUM1
 read -p "请输入第二个数:" NUM2
 echo "您输入的两个数为:$NUM1和$NUM2"
 SUM=$(expr $NUM1 + $NUM2)
 echo "两个数的和为:$SUM"
}
sum
[root@localhost ~]# ./SUM.sh 
请输入第一个数:5
请输入第二个数:8
您输入的两个数为:5和8
两个数的和为:13

2.2 函数的作用范围

■函数在Shell脚本中仅在当前Shell环境中有效
■Shell脚本中变量默认全局有效
■将变量限定在函数内部使用local命令
■示例
●函数内部变量通过local来实现
◆通过定义myfun函数,在其内部设置局部变量i
◆函数内部和外部分别赋值,进行结果验证

2.3 函数的参数

■参数的用法
函数名称 参数1 参数2 参数3 …
参数的表示方法
$1 $2 … ${10} ${11}
■示例
●通过函数参数将日志信息写入文件
◆通过定义appendfile函数实现

2.4 递归函数

■调用自己本身的函数
■示例
●递归遍历记录
◆通过定义递归函数list_files来实现

[root@localhost ~]# vi fun.sh
#!/bin/bash
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.sh 
[root@localhost ~]# ./fun.sh 
anaconda
 anaconda.log
 ifcfg.log
 journal.log
 ks-script-_jzieq.log
 ks-script-VOaRnV.log
 packaging.log
 program.log
 storage.log
 syslog
 X.log
audit
 audit.log

三、 Shell数组

3.1 Shell数组

■应用场景包括
●获取数组长度
●获取元素长度
●遍历元素
●元素切片
●元素替换
●元素删除
●…
■数组定义方法
●方法1:数组名=(vlaue0 vlaue1 vlaue2 …)
●方法2:数组名=([0]=vlaue [1]=vlaue [2]=vlaue …)
方法3:列表名=“value0 value1 value2 …”
数组名=($列表名)
●方法4:数组名[0]=“value”
数组名[1]=“value”
数组名[2]=“value”

■数组包括的数据类型
●数值类型
●字符类型
◆使用""或’'定义

示例:
■获取数组长度

[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

■读取某下标赋值

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

■数组遍历

[root@localhost ~]# vi 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

■数组切片

[root@localhost ~]# arr=(1 2 3 4 5)
[root@localhost ~]# echo ${arr[@]}  ##输出整个数组##
1 2 3 4 5
[root@localhost ~]# echo ${arr[@]:0:2}  ##${数组名[@或*]:起始位置:长度}
1 2
[root@localhost ~]# echo ${arr[@]:2:3}
3 4 5

■数组替换

[root@localhost ~]# arr=(1 2 3 4 5)
[root@localhost ~]# echo ${arr[@]/4/66}  ##${数组名[@或*]/查找字符/替换字符}##
1 2 3 66 5
[root@localhost ~]# echo ${arr[@]}  ##不会替换数组原有字符##
1 2 3 4 5
[root@localhost ~]# arr=(${arr[@]/4/66})  ##要实现改变原有数组,可通过重新赋值实现#
[root@localhost ~]# echo ${arr[@]}
1 2 3 66 5

■数组删除

[root@localhost ~]# arr=(1 2 3 4 5)
[root@localhost ~]# unset arr   ##删除数组##
[root@localhost ~]# echo ${arr[*]}

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

3.2 Shell脚本测试

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

 

posted on 2022-10-25 13:59  知趣。  阅读(74)  评论(0编辑  收藏  举报