shell-循环语句、函数、数组的介绍和示例

一、循环语句

1.1 for循环语句

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

语句结构
for 变量名 in 取值列表
do
	命令序列
done

在这里插入图片描述
例1:使用for语句批量添加用户

用户名存放在users.txt文件中,每行一个

[root@localhost opt]# vim user.txt
zhangsan
lisi
wangwu
[root@localhost opt]# vim useradd.sh
#!/bin/bash
user=$(cat /opt/user.txt)
for a in $user
do
  useradd $a
  echo "123456" | passwd --stdin $a
  echo "$a添加成功"
done
[root@localhost opt]# . useradd.sh 
更改用户 zhangsan 的密码 。
passwd:所有的身份验证令牌已经成功更新。
zhangsan添加成功
更改用户 lisi 的密码 。
passwd:所有的身份验证令牌已经成功更新。
lisi添加成功
更改用户 wangwu 的密码 。
passwd:所有的身份验证令牌已经成功更新。
wangwu添加成功

同样的可以批量删除用户

[root@localhost opt]# vim useradd.sh
#!/bin/bash
user=$(cat /opt/user.txt)
for a in $user
do
  userdel -r $a
 #echo "123456" | passwd --stdin $a
  echo "$a删除成功"
done
[root@localhost opt]# . useradd.sh 
zhangsan删除成功
lisi删除成功
wangwu删除成功

例2:根据IP地址检查主机状态

检测IP地址192.168.179.0-192.168.179.10段落
使用ping命令检测各主机的连通性

[root@localhost opt]# vim ping.sh

#!/bin/bash
for ((i=1;i<=10;i++))
do
  ping -c 3 -i 0.2 -w 3 "192.168.179.$i" > /dev/null
 if [ $? -eq 0 ];then
   echo "主机192.168.179.$i在线"
 else
   echo "主机192.168.179.$i不在线"
 fi
done
[root@localhost opt]# . ping.sh 
主机192.168.179.1在线
主机192.168.179.2在线
主机192.168.179.3不在线
主机192.168.179.4不在线
主机192.168.179.5不在线
主机192.168.179.6不在线
主机192.168.179.7不在线
主机192.168.179.8不在线
主机192.168.179.9不在线
主机192.168.179.10不在线

1.2 let命令

  • let 对整数进行数学运算
  • let和双小括号 (( )) 一样,let 命令也只能进行整数运算,不能对小数(浮点数)或者字符串进行运算
语法格式
let 表达式
或
let "表达式"
或
let '表达式'
以上方式都等价于 ((表达式))
  • 当表达式中含有 Shell 特殊字符(例如 |)时,需要用双引号" "或者单引号’ '将表达式包围起来
  • 和 (( )) 类似,let 命令也支持一次性计算多个表达式,并且以最后一个表达式的值作为整个 let 命令的执行结果

例:计算1-10偶数/奇数的和

[root@localhost opt]# vim hehe.sh
#!/bin/bash
num=0
for ((i=0;i<=10;i+=2))
do
  let num+=$i
done
  echo "偶数和为:$num"
[root@localhost opt]# . hehe.sh 
偶数和为:30

[root@localhost opt]# vim hehe.sh
#!/bin/bash
num=0
for ((i=1;i<=10;i+=2))
do
  let num+=$i
done
  echo "奇数和为:$num"
[root@localhost opt]# . hehe.sh 
奇数和为:25

1.3 while循环语句

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

语句结构
while 条件测试操作
do
	命令序列
done

在这里插入图片描述
例1:使用while循环语句输出1-10数字

[root@localhost opt]# vim 10.sh

#!/bin/bash
i=1
while [ $i -le 10 ] 
do
  echo "$i"
  let i++
done
[root@localhost opt]# . 10.sh 
1
2
3
4
5
6
7
8
9
10

while死循环
while true:死循环有时候也有奇效,可与用户交互

[root@localhost opt]# vim 10.sh 

#!/bin/bash
while true
do
 read -p "请输入yes退出:" key
  if [ $key = yes ];then
    break
  fi
done
echo "正常退出"
[root@localhost opt]# . 10.sh 
请输入yes退出:no
请输入yes退出:cc
请输入yes退出:sgh
请输入yes退出:yes
正常退出

例3:使用while批量添加用户

  • 用户名称以stu开头,按数字顺序进行编号
  • 一共添加20个用户,即stu1,stu2…stu20
#!/bin/bash
i=0
while [ $i -le 19 ]
do
  let i++
  useradd stu$i
  echo "123456" | passwd --stdin stu$i &> /dev/null
  echo "stu$i添加成功"
done
echo "添加完毕"
[root@localhost opt]# ./useradd.sh 
stu1添加成功
stu2添加成功
stu3添加成功
stu4添加成功
stu5添加成功
stu6添加成功
stu7添加成功
stu8添加成功
stu9添加成功
stu10添加成功
stu11添加成功
stu12添加成功
stu13添加成功
stu14添加成功
stu15添加成功
stu16添加成功
stu17添加成功
stu18添加成功
stu19添加成功
stu20添加成功
添加完毕

1.4 untli循环语句

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

until 条件测试操作
do
 命令序列
done

在这里插入图片描述
例:通过循环累加的方式计算1–50的和

#!/bin/bash
i=1
S=0
until [ $i -eq 51 ]
do
 let S+=$i
 let i++

done
echo "$S"
[root@localhost opt]# ./qiuhe.sh 
1275

二、shell函数

2.1 shell函数概述

  • shell一个非常重要的特性是它可作为一种编程语言来使用。
  • 因为shell是一个解释器,所以它不能对为它编写的程序进行编译,而是在每次从磁盘加载这些程序时对它们进行解释。而程序的加载和解释都是非常耗时的。
  • 针对此问题,许多shell(如BourneAgainShell)都包含shell函数,shell把这些函数放在内存中,这样每次需要执行它们时就不必再从磁盘读入。
  • shell还以一种内部格式来存放这些函数,这样就不必耗费大量的时间来解释它们
  • shell函数将命令序列按格式写在一起
  • 可以方便重复使用命令序列

2.2 shell函数定义

通过使用函数,可以对程序进行更加好的组织。将一些相对独立的代码变成函数,
可以提高程序的可读性和重用性。避免重复编写大量相同的代码。

方法1:

函数名() {
   函数体
   return n
}

方法2:(更加规范)

function 函数名() {
     函数体
     return n    
}
  • 其中,return返回的是状态码,需要使用$?调取
  • echo 返回的是值,使用变量调用
  • 传参:指位置变量
  • 可以带function fun() 定义,也可以直接fun() 定义,不带任何参数
  • 参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255
#!/bin/bash
function sum(){
#命令序列
   read -p "请输入第一个整数:" num1
   read -p "请输入第二个整数:" num2
   sum=$[$num1+$num2]
  #echo 返回的是处理结果值
  echo $sum
  #return返回的是状态码
  return 100
}
number=`sum`
echo $?
echo $number
[root@localhost opt]# bash han.sh 
请输入第一个整数:4
请输入第二个整数:4
100
8

2.3 调用函数的方法

  • 函数名 [参数1($1)] [参数2($2)]
  • 在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数…
  • 10不能获取第十个参数,获取第十个参数需要{10}。当n>=10时,需要使用${n}来获取参数
    例:
[root@localhost ~]# vim han.sh

#!/bin/bash

function fun1() {
    echo "I like you"
}

count=1
while [ $count -le 5 ]
do
    fun1
    ((count++))
done

echo "Eed of loop" 

fun1

echo "Eed of scritp" 
[root@localhost ~]# bash han.sh 
I like you
I like you
I like you
I like you
I like you
Eed of loop
I like you
Eed of scritp

2.4 函数的作用范围

  • 函数在Shell脚本中仅在当前Shell环境中有效
  • Shell脚本中变量默认全局有效
  • 将变量限定在函数内部使用local命令
    例:
[root@localhost opt]# vim han.sh 

#!/bin/bash
function sum(){
#命令序列
   read -p "请输入第一个整数:" num1
   read -p "请输入第二个整数:" num2
   sum=$[$num1+$num2]
  #echo 返回的是处理结果值
  local score=100
  echo "函数内$score"
  echo "和:$sum"
}
sum
echo "函数外$score"
        [root@localhost opt]# bash han.sh 
请输入第一个整数:5
请输入第二个整数:7
函数内100
和:12
函数外           

2.5 递归函数

  • 调用自己本身的函数
    例:递归遍历目录
#!/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 opt]# bash hanshu.sh 
anaconda
  anaconda.log
  ifcfg.log
  journal.log
  ks-script-Nw8yvE.log
  packaging.log
  program.log
  storage.log
  syslog
  X.log
audit
  audit.log
......

三、shell数组

3.1应用场景包括

  • 获取数组长度
    使用for循环获取具体信息,使用下标或索引标记数组中数据的位置
    可以存放多种数据,如:整型,长整形,浮点型(单精度,双精度),字符串等
  • 获取元素长度
  • 遍历元素
  • 元素切片
  • 元素替换
  • 元素删除
  • 数组下标从0开始算
  • 数组长度从1开始算
    长度为4,数组长度表示为1,2,3,4;数组下标表示为0,1,2,3
  • shell中数组是可变长的

3.2 数组定义方法

方法一:

基本格式
数组名=(value0 value1 value2...[root@localhost opt]# list=(11 22 33 44 55)
[root@localhost opt]# echo ${list[*]}
11 22 33 44 55
[root@localhost opt]# 

方法二:

基本格式
数组名=([0]=value [1]=value [2]=value...[root@localhost opt]# list=([0]=55 [1]=44 [2]=33 [3]=22 [4]=11)
[root@localhost opt]# echo ${list[*]}
55 44 33 22 11

方法三:

基本格式
列表名=“value0 value1 value2”
数组名=($列表名)
[root@localhost opt]# sum="22 44 66 88 99"
[root@localhost opt]# list=($sum)
[root@localhost opt]# echo ${list[*]}
22 44 66 88 99

方法四:

基本格式
数组名[0]=“value”
数组名[1]=“value”
数组名[2]=“value”
[root@localhost opt]# list[0]="33"
[root@localhost opt]# list[1]="35"
[root@localhost opt]# list[2]="55"
[root@localhost opt]# list[3]="67"
[root@localhost opt]# list[4]="78"
[root@localhost opt]# echo ${list[*]}
33 35 55 67 78

3.3 数组包括的数据类型与数组操作

3.3.1 数组包括的数据类型

  • 数值类型
  • 字符类型
    使用“”或‘’定义
    数组只可存放数值或字符

3.3.2 数组操作

  • 获取数组长度
基本格式
${#数组名[@/*]}
例如
[root@localhost opt]# echo ${list[*]}
33 35 55 67 78
[root@localhost opt]# echo ${#list[*]}
5
  • 读取某下标赋值
基本格式
${数组名[下标]}
例如
[root@localhost opt]# echo ${list[*]}
33 35 55 67 78
[root@localhost opt]# echo ${list[1]}
35
[root@localhost opt]# echo ${list[0]}
33
  • 数组遍历

通过查看数组中的所有元素完成相应的操作

[root@localhost opt]# for v in ${num[*]}
> do
> echo $v
> done
11
22
33
44
55

例如:输出一组数组中的最大值

[root@localhost opt]# vim num.sh 

#!/bin/bash
ssr=(32 45 77 18 67)
num=0
for ((i=0;i<${#ssr[*]};i++))
do
  if [ ${ssr[i]} -ge $num ];then
    num=${ssr[i]}
    else
    continue
  fi
done
echo $num
[root@localhost opt]# bash num6.sh 
77
  • 数组切片
#{数组名[@/*]:起始位置:长度}
[root@localhost opt]# num=(11 22 33 44 55)
[root@localhost opt]# echo ${num[*]}
11 22 33 44 55
[root@localhost opt]# echo ${num[*]:1:3}
22 33 44
  • 数组的替换
${数组名[@/*]/查找字符、替换字符}
[root@localhost opt]# num=(22 44 66 88 99)
[root@localhost opt]# echo ${num[*]}
22 44 66 88 99
[root@localhost opt]# echo ${num[*]/44/55}   #临时替换
22 55 66 88 99
[root@localhost opt]# echo ${num[*]}
22 44 66 88 99
[root@localhost opt]# num=(${num[*]/44/55})  #永久替换
[root@localhost opt]# echo ${num[*]}
22 55 66 88 99
  • 数组删除
[root@localhost opt]# num=(12 23 34 45 56)
[root@localhost opt]# unset num[1]
[root@localhost opt]# echo ${num[*]}
12 34 45 56
[root@localhost opt]# unset num
[root@localhost opt]# echo ${num[*]}

[root@localhost opt]# 

猜你喜欢

转载自blog.csdn.net/weixin_47153988/article/details/107481361