Shell 脚本中的循环语句、函数与数组

文章目录

Shell 脚本中的循环语句、函数与数组

1. for 循环

1.1 for 循环语法结构

1.1.1 列表循环
for 变量名 in {list}
do
    command
done
1.1.2 不带列表循环
for 变量名
do
    command
done
1.1.3 类C风格的for循环
for ((expr1; expr2; expr3))
do
    command
done

1.2 案例

1.2.1 打印1-5这5个数字
#!/bin/bash
for i in {1..5}
do
    echo $i
done

image-20240804202452922

1.2.2 打印5次hello world
#!/bin/bash
for i in {1..5}
do
    echo hello world
done

image-20240806084638194

1.2.3 打印abcde
#!/bin/bash
for i in a b c d e
do
    echo $i
done

image-20240806084521518

1.2.4 输出0-50之间的偶数
#!/bin/bash
for i in {0..50..2}
do
    echo $i
done

image-20240806084735261

1.3 小技巧:花括号 {}seqfor 循环的应用

  • for i in {1..50..2} 1-50的奇数
  • for i in {2..50..2} 1-50的偶数
  • for i in {10..1} 1-10倒序排列
  • for i in $(seq 10) 1-10正序排列
  • for i in $(seq 10 -1 1) 1-10倒序排列
  • for i in $(seq 1 2 10) 1-10的奇数,中间为步长
  • for i in $(seq 0 2 10) 1-10的偶数,中间为步长

1.4 实际案例

1.4.1 批量添加用户

方法1:以后缀批量变化添加

#!/bin/bash
for i in {1..10}
do
userdel -r xiewei$i
echo "已删除xiewei1-10用户"
done

image-20240806085206109

方法2:脚本批量添加用户

#!/bin/bash
ULIST=$(cat /root/users.txt)
for UNAME in $ULIST
do
    useradd $UNAME
    echo "123456" | passwd --stdin $UNAME &>/dev/null
done

方法3:批量删除用户

#!/bin/bash
ULIST=$(cat /root/users.txt)
for UNAME in $ULIST
do
    userdel -r $UNAME &>/dev/null
done

image-20240806085928716

1.4.2 根据IP地址列表检查主机状态
#!/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

image-20240806091109604

1.4.3 根据IP地址段检查主机状态
#!/bin/bash
network="192.168.10"
for addr in {1..254}
do
    ping -c 2 -i 0.5 -W 3 $network.$addr &> /dev/null
    if [ $? -eq 0 ];then
        echo "$network.$addr is up"
    else
        echo "$network.$addr is down"
    fi
done

image-20240806092106737

2. while 循环

2.1 while 循环的语法结构

while 表达式
do
    command
done

2.2 死循环

2.2.1 写一个永远为真的表达式
while [ 1 -eq 1 ]
do
    command
done
2.2.2 使用 true
while true
do
    command
done
2.2.3 使用 :(空命令)
while :
do
    command
done

2.3 案例

2.3.1 打印1-5
#!/bin/bash
i=1
while [ $i -le 5 ]
do
    echo $i
    let i++
done
echo "最后i的值为: $i"

image-20240806093307331

2.3.2 输出1-100之间不能被3整除的数字
#!/bin/bash
i=1
while [ $i -le 100 ]
do
    if [[ $i%3 -ne 0 ]]
    then 
        echo "$i"
    fi
    let i++
done

image-20240806093734804

2.3.3 监控某服务(httpd)运行状态
while ps aux | grep httpd | grep -v grep &> /dev/null
do
    echo "httpd 正在运行中"
    sleep 2
done
echo "httpd 不在运行"

image-20240806094807184

2.4 实际案例

2.4.1 实时监控本机内存和硬盘剩余空间
#!/bin/bash
#提取根分区剩余空间
disk_size=$(df / | awk '/\//{print $4}')
#提取内存剩余空间
mem_size=$(free | awk '/Mem/{print $4}')
while :
do
    #注意内存和磁盘提取的空间大小都是以Kb 为单位
    if [ $disk_size -le 512000 -a $mem_size -le 1024000 ];then 
        mail -s "Warning" root <<EOF
Insufficient resources,资源不足
EOF
    fi 
done

image-20240806095403591

3. until 循环

until 循环和 while 循环相反,条件为假进入循环,条件为真退出循环。

3.1 语法结构

until 表达式
do
    command
done

3.2 案例

3.2.1 计算1-50的和
#!/bin/bash
i=0
s=0
until [ $i -eq 51 ]
do
    let s+=i
    let i++
done
echo $s

image-20240806095729117

4. 循环控制语句

4.1 continue

continue 语句用于跳过本次循环的剩余部分,重新开始下一次循环。

4.1.1 案例:打印1-5的数字,3不打印
#!/bin/bash
for ((i=1;i<=5;i++))
do
    if [ $i -eq 3 ];then
        continue
    else
        echo $i
    fi
done

image-20240806100242888

4.2 break

break 语句用于立即停止循环,并执行循环体外的代码。

4.2.1 案例:打印1-10的数字,7后面的都不打印
#!/bin/bash
for ((i=1;i<=10;i++))
do
    if [ $i -eq 8 ];then
        break
    else
        echo $i
    fi
done

image-20240806100440244

4.3 exit

exit 语句用于立即退出脚本,并返回一个状态码。

4.3.1 案例:打印1-5的数字,3时退出程序
for i in {1..5}
do
    if [ $i -eq 3 ];then
        exit 100 
    else
        echo $i
    fi
done
echo hi

image-20240806100602520

5. Shell 函数

5.1 函数的定义

5.1.1 函数的定义方法

方法1:

function 函数名 {
    command
}

方法2:

函数名() {
    command
}

5.2 函数的调用

直接在脚本里定义函数的代码块后写函数名即可完成调用。

#!/bin/bash
function fun1 {
    echo "this is a function!"
}

fun1

image-20240809160632529

5.3 函数的返回值

return 表示退出函数并返回一个退出值,脚本中可以用 $? 变量显示该值。

5.3.1 案例:返回用户输入的数字的两倍
#!/bin/bash
function

 test1 {
    read -p "请输入一个数字:" num
    return $[$num*2]
}
test1
echo $?

image-20240809161350326

5.4 函数传参

5.4.1 两个数求和
#!/bin/bash
sum(){
    read -p "请输入第一个数:" NUM1
    read -p "请输入第二个数:" NUM2
    echo "你输入的两个数为: $NUM1$NUM2 "
    SUM=$(( NUM1 + NUM2 ))
    echo "两个数的和为: $SUM"
}
sum

image-20240809162639566

5.4.2 通过脚本传递参数给函数中的位置参数
#!/bin/bash
add (){
    let sum=$1+$2
    echo $sum
}

add $1 $2   # 调用脚本时传递参数
add 20 30

image-20240809163210386

5.5 函数的递归

5.5.1 计算5的阶乘
#!/bin/bash
fa () {
    if [ $1 -eq 1 ]
    then
        echo 1
    else
        local tp=$[$1 - 1]
        local res=$(fa $tp)
        echo $[$1 * $res]
    fi
}

read -p "请输入:" num
res=$(fa $num)
echo $res

image-20240809165547715

6. 数组的定义

6.1 数组的定义方法

方法1:

num=(11 22 33 44)

方法2:

num=([0]=55 [1]=66 [2]=77 [4]=88)

方法3:

list="11 12 13 14"
num=($list)

方法4:

数组名[0]="value"
数组名[1]="value"
数组名[2]="value"

6.2 获取数组的长度

arr_length=${#arr_number[*]}

6.3 获取数据列表

echo ${arr_number[*]}
echo ${arr_number[@]}

6.4 数组元素遍历

#!/bin/bash
arr=(1 2 3 4 5 6)
for i in ${arr[*]}
do
    echo $i
done

image-20240809171105179

6.5 数组(元素)替换

arr=(1 2 3 4 5)
echo ${arr[@]/3/55}   # 替换元素3为55
echo ${arr[@]}
arr=(${arr[@]/3/55})  # 实现改变原有数组,如果注释掉原数组不变。
echo ${arr[@]}

image-20240809171351965

6.6 数组删除

arr=(1 2 3 45)
unset arr            # 删除数组
echo ${arr[*]}

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

image-20240809171827037

6.7 数组排序算法:冒泡排序

6.7.1 基本思想

冒泡排序的基本思想是对比相邻的两个元素值,如果满足条件就交换元素值,把较小的元素移动到数组前面,把大的元素移动到数组后面(也就是交换两个元素的位置),这样较小的元素就像气泡一样从底部上升到顶部。

6.7.2 算法思路
#!/bin/bash
array=(90 70 60 40 50 30)
echo "old_array:${array[*]}"
lt=${#array[*]}
# 定义比较轮数,比较轮数为数组长度减1,从1开始
for ((i=1; i<$lt; i++))
do
    # 确定比较元素的位置,比较相邻两个元素,较大的数往后放,比较次数随比较轮数而减少
    for ((j=0; j<$lt-i; j++))
    do
        # 定义第一个元素的值
        first=${array[$j]}
        # 定义第二个元素的值
        k=$[$j+1]
        second=${array[$k]}
        # 如果第一个元素比第二个元素大就互换
        if [ $first -gt $second ]
        then
            # 把第一个元素值保存到临时变量中
            temp=$first
            # 把第二个元素值赋给第一个元素
            array[$j]=$second
            # 把临时变量(也就是第一个元素原值)赋给第二个元素
            array[$k]=$temp
        fi
    done
done
# 输出排序后的数组
echo "new_array:${array[*]}"

image-20240809174544545

6.8 输入数组元素并排序

#!/bin/bash
# 存入元素
k=0
while true
do
    read -p "是否继续存入元素:" doing
    if [ $doing == "no" ];then
        break
    fi
    read -p "请输入第$[$k+1]个元素:" key
    score[$k]=$key
    let k++
done
# 外层为轮
for ((i=1;i<${#score[*]};i++));do
    # 内层为次
    for ((j=0;j<${#score[*]}-i ;j++));do
        # 两数交换
        if [ ${score[$j]} -gt ${score[`expr $j + 1`]} ];then
            tmp=${score[`expr $j + 1`]}
            score[`expr $j + 1`]=${score[$j]}
            score[$j]=$tmp
        fi
    done
done
echo ${score[*]}

ray:${array[*]}"


[外链图片转存中...(img-DSf2up1f-1723197200361)]

### 6.8 输入数组元素并排序

```bash
#!/bin/bash
# 存入元素
k=0
while true
do
    read -p "是否继续存入元素:" doing
    if [ $doing == "no" ];then
        break
    fi
    read -p "请输入第$[$k+1]个元素:" key
    score[$k]=$key
    let k++
done
# 外层为轮
for ((i=1;i<${#score[*]};i++));do
    # 内层为次
    for ((j=0;j<${#score[*]}-i ;j++));do
        # 两数交换
        if [ ${score[$j]} -gt ${score[`expr $j + 1`]} ];then
            tmp=${score[`expr $j + 1`]}
            score[`expr $j + 1`]=${score[$j]}
            score[$j]=$tmp
        fi
    done
done
echo ${score[*]}

image-20240809175039558

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值