shell循环语句

目录

一, 循环语句

1.for循环语句

1.1 列表循环

1.2 不带列表循环

1.3 类c语言风格

 2.while循环语句

3.untli循环语句

2.循环控制语句

1 . continue

2 . break

3 . exit

二,shell函数

1. 函数定义

2.函数返回退出

2.1使用 return 结束函数

2.1使用 exit 结束脚本

3.函数的调用

3.1函数调用注意事项

a.函数名必须唯一

b.调用函数之前必须先定义

错误示例

正确示例

c.函数定义的位置

d.嵌套调用时的注意事项

4.函数传递参数

5.函数的作用范围

6.函数的参数

6.1 函数参数

6.2 脚本参数

7.函数的递归

8.计算阶乘

三,Shell数组

1.根据用途分类

2.数组的定义

2.1直接初始化数组

2.2指定索引初始化数组

2.3先赋值给变量,然后引用变量初始化数组

2.4根据下标定义数组

3.冒泡排序

3.1冒泡排序是什么

3.2冒泡排序的步骤


一, 循环语句

1.for循环语句

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

格式

for  变量名 in 取值列表

do

    命令序列

done

1.1 列表循环

[root@localhost /home]# vim demo32.sh
#!/bin/bash
for i in {a..c}
do
  echo $i
done
~ 
[root@localhost /home]# chmod +x demo32.sh
[root@localhost /home]# ./demo32.sh
a
b
c

[root@localhost /home]# vim demo31.sh
#!/bin/bash
for i in {1..5}
do
  echo $i
done
~     
[root@localhost /home]# chmod +x demo31.sh
[root@localhost /home]# ./demo31.sh
1
2
3
4
5

[root@localhost /home]# vim demo33.sh
#!/bin/bash
for i in `seq 5`     #反引号
do
  echo $i
done
~
[root@localhost /home]# ./demo33.sh
1
2
3
4
5

[root@localhost /home]# vim demo34.sh
#!/bin/bash
for i in a b c
do
  echo $i
done
~    
[root@localhost /home]# chmod +x demo34.sh
[root@localhost /home]# ./demo34.sh
a
b
c

[root@localhost /home]# vim demo35.sh
#!/bin/bash
a=10
for i in `seq $a`
do
  echo $i
done
~ 
[root@localhost /home]# chmod +x demo35.sh
[root@localhost /home]# ./demo35.sh
1
2
3
4
5
6
7
8
9
10

[root@localhost /home]# vim demo36.sh
#!/bin/bash
for i in {1..5}
do
  echo hello
done
~ 
[root@localhost /home]# chmod +x denmo36.sh
chmod: 无法访问"denmo36.sh": 没有那个文件或目录
[root@localhost /home]# chmod +x demo36.sh
[root@localhost /home]# ./demo36.sh
hello
hello
hello
hello
hello

[root@localhost /home]# vim demo37.sh
#!/bin/bash
for i in a b c d e f
do
  echo $i
done
~
[root@localhost /home]# chmod +x demo37.sh
[root@localhost /home]# ./demo37.sh
a
b
c
d
e
f

[root@localhost /home]# vim demo38.sh
#!/bin/bash
for i in {1..50..2}
do
  echo $i
done
~ 
[root@localhost /home]# chmod +x demo38.sh
[root@localhost /home]# ./demo38.sh
1
3
5
7
9
11
13
15
17
19
21
23
25
27
29
31
33
35
37
39
41
43
45
47
49

[root@localhost /home]# vim demo39.sh
#!/bin/bash
for i in {2..50..2}
do
  echo $i
done
~ 
[root@localhost /home]# chmod +x demo39.sh
[root@localhost /home]# ./demo39.sh
2
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
34
36
38
40
42
44
46
48
50

[root@localhost /home]# vim demo40.sh
#!/bin/bash
for i in {10..1}
do
  echo $i
done
~     
[root@localhost /home]# chmod +x demo40.sh
[root@localhost /home]# ./demo40.sh
10
9
8
7
6
5
4
3
2
1

[root@localhost /home]# vim demo41.sh
#!/bin/bash
for i in $(seq 10 -1 1)     #()内的看做一个整体,[]里的符合其中一个就行
do
  echo $i
done

[root@localhost /home]# bash -n demo41.sh
[root@localhost /home]# vim demo41.sh
[root@localhost /home]# ./demo41.sh
10
9
8
7
6
5
4
3
2
1

[root@localhost /home]# vim demo42.sh
#!/bin/bash
for i in $(seq 0 4 10)  #步长为4
do
  echo $i
done
~  
[root@localhost /home]# ./demo42.sh
0
4
8

1.2 不带列表循环

[root@localhost /home]# vim demo42.sh
#!/bin/bash
for i
do
  echo hello
done
~ 
[root@localhost /home]# chmod +x demo43.sh 
[root@localhost /home]# ./demo43.sh
[root@localhost /home]# ./demo43.sh a      #a赋值给变量i,i有值就开始执行
hello

[root@localhost /home]# vim demo44.sh
#!/bin/bash
for i
do
  echo $i
done
~ 
[root@localhost /home]# bash demo44.sh hello
hello

1.3 类c语言风格

运算符

++ 自身变量+1

-- 自身变量-1

+=5 自身变量+5

-=5 自身变量-5

*=5 自身变量*5

/=5 自身变量/5

%=5 自身变量%5

[root@localhost /home]# vim demo45.sh 
#!/bin/bash
for ((a=1; a<=7;a++))
do
  echo $a
done
~ 
[root@localhost /home]# chmod +x demo45.sh 
[root@localhost /home]# ./demo45.sh 
1
2
3
4
5
6
7

[root@localhost /home]# vim demo46.sh 
#!/bin/bash
set -x
for ((a=1;a<=7;a+=5))
do
  echo $a
done
~
[root@localhost /home]# chmod +x demo46.sh
[root@localhost /home]# ./demo46.sh 
+ (( a=1 ))
+ (( a<=7 ))
+ echo 1
1
+ (( a+=5 ))
+ (( a<=7 ))
+ echo 6
6
+ (( a+=5 ))
+ (( a<=7 ))

[root@localhost /home]# vim demo47.sh 
#!/bin/bash
set -x
NU=0
for ((a=2;a<=11;a+=3))
do
  let NU=$a+$NU
done
~ 
[root@localhost /home]#chmod +x demo47.sh
[root@localhost /home]# ./demo47.sh
+ NU=0
+ (( a=2 ))
+ (( a<=11 ))
+ let NU=2+0
+ (( a+=3 ))
+ (( a<=11 ))
+ let NU=5+2
+ (( a+=3 ))
+ (( a<=11 ))
+ let NU=8+7
+ (( a+=3 ))
+ (( a<=11 ))
+ let NU=11+15
+ (( a+=3 ))
+ (( a<=11 ))

[root@localhost /home]# vim demo48.sh 
#!/bin/bash
NU=0
for ((a=1;a<=100;a+=2))
do
  let NU=$a+$NU
done
  echo "1~100的奇数的和:$NU"
~
[root@localhost /home]# chmod +x demo48.sh
[root@localhost /home]# ./demo48.sh
+ NU=0
+ (( a=1 ))
+ (( a<=100 ))
+ let NU=1+0
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=3+1
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=5+4
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=7+9
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=9+16
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=11+25
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=13+36
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=15+49
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=17+64
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=19+81
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=21+100
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=23+121
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=25+144
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=27+169
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=29+196
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=31+225
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=33+256
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=35+289
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=37+324
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=39+361
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=41+400
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=43+441
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=45+484
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=47+529
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=49+576
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=51+625
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=53+676
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=55+729
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=57+784
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=59+841
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=61+900
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=63+961
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=65+1024
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=67+1089
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=69+1156
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=71+1225
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=73+1296
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=75+1369
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=77+1444
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=79+1521
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=81+1600
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=83+1681
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=85+1764
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=87+1849
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=89+1936
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=91+2025
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=93+2116
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=95+2209
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=97+2304
+ (( a+=2 ))
+ (( a<=100 ))
+ let NU=99+2401
+ (( a+=2 ))
+ (( a<=100 ))
+ echo $'1~100\347\232\204\345\245\207\346\225\260\347\232\204\345\222\214:2500'
1~100的奇数的和:2500

[root@localhost /home]# vim demo49.sh 
#!/bin/bash
for i in {1..5}
do
  useradd test$i
  echo "123"|passwd --stdin test$i   #加上&> /dev/null可以将显示的信息不显示在台前
done
~  
[root@localhost /home]# chmod +x demo49.sh 
[root@localhost /home]# ./demo49.sh 
更改用户 test1 的密码 。
passwd:所有的身份验证令牌已经成功更新。
更改用户 test2 的密码 。
passwd:所有的身份验证令牌已经成功更新。
更改用户 test3 的密码 。
passwd:所有的身份验证令牌已经成功更新。
更改用户 test4 的密码 。
passwd:所有的身份验证令牌已经成功更新。
更改用户 test5 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[root@localhost /home]# tail -5 /etc/passwd
test1:x:10088:10088::/home/test1:/bin/bash
test2:x:10089:10089::/home/test2:/bin/bash
test3:x:10090:10090::/home/test3:/bin/bash
test4:x:10091:10091::/home/test4:/bin/bash
test5:x:10092:10092::/home/test5:/bin/bash

[root@localhost /home]# cp demo49.sh demo51.sh
[root@localhost /home]# vim demo51.sh
#!/bin/bash
do
  userdel -r test$i
done
~ 
[root@localhost /home]# ./demo51.sh
[root@localhost /home]# tail -10 /etc/passwd
fff8:x:1017:1017::/home/fff8:/bin/bash
fff9:x:1018:1018::/home/fff9:/bin/bash
fff10:x:1019:1019::/home/fff10:/bin/bash
UNT:x:1020:1020::/home/UNT:/bin/bash
xxxlll:x:10085:10085::/home/xxxlll:/bin/bash
testuser1:x:10086:10086::/home/testuser1:/bin/bash
testuser2:x:10087:10087::/home/testuser2:/bin/bash
user1:x:10093:10093::/home/user1:/bin/bash
user2:x:10094:10094::/home/user2:/bin/bash
user3:x:10095:10095::/home/user3:/bin/bash

[root@localhost /home]# vim demo50.sh 
#!/bin/bash
#set -x
touch /home/user.txt
echo 'user1' > /home/user.txt
echo 'user2' >> /home/user.txt
echo 'user3' >> /home/user.txt
USER=$(cat /home/user.txt)
for USERADD in $USER
do
  useradd $USERADD
  echo "88888888" | passwd --stdin $USERADD &> /dev/null
done
~  
[root@localhost /home]# bash -n demo50.sh
[root@localhost /home]# chmod +x demo50.sh
[root@localhost /home]# ./demo50.sh 
[root@localhost /home]# tail -5 /etc/passwd
test4:x:10091:10091::/home/test4:/bin/bash
test5:x:10092:10092::/home/test5:/bin/bash
user1:x:10093:10093::/home/user1:/bin/bash
user2:x:10094:10094::/home/user2:/bin/bash
user3:x:10095:10095::/home/user3:/bin/bash

root@localhost /home]# vim demo51.sh 
#!/bin/bash
for i in {1..5}
do
  userdel -r test$i
done
~
[root@localhost /home]# chmod +x demo51.sh 
[root@localhost /home]# ./demo51.sh 

[root@localhost /home]# vim demo52.sh
#!/bin/bash
network="192.168.10"
for addr in {1..254}
do
{
 ping -c 2 i 0.2 -w 6 $network.$addr &> /dev/null  
  if [ $? -eq 0 ]; then
    echo "$network.$addr is up"
  else
    echo "$network.$addr is down"
  fi
} &    #加上{} &带边后台运行想,一不影响操作,二运行快
done
~ 
[root@localhost /home]# chmod +x demo52.sh
[root@localhost /home]# ./demo52.sh
192.168.10.1 is down
192.168.10.2 is down
192.168.10.3 is down
192.168.10.4 is down
192.168.10.5 is down
192.168.10.6 is down
192.168.10.7 is down
192.168.10.8 is down
192.168.10.9 is down
192.168.10.10 is down
192.168.10.11 is down
192.168.10.12 is down
192.168.10.13 is down
192.168.10.14 is down
192.168.10.15 is down
192.168.10.16 is down
192.168.10.17 is down
192.168.10.18 is down
192.168.10.19 is down
192.168.10.20 is down
192.168.10.21 is down
192.168.10.22 is down
192.168.10.23 is down
192.168.10.24 is down
192.168.10.25 is down
192.168.10.26 is down
192.168.10.27 is down
192.168.10.28 is down
192.168.10.29 is down
192.168.10.30 is down
192.168.10.31 is down
192.168.10.32 is down
192.168.10.33 is down
192.168.10.34 is down
192.168.10.35 is down
192.168.10.36 is down
192.168.10.37 is down
192.168.10.38 is down
192.168.10.39 is down
192.168.10.40 is down
192.168.10.41 is down
192.168.10.42 is down
192.168.10.43 is down
192.168.10.44 is down
192.168.10.45 is down
192.168.10.46 is down
192.168.10.47 is down
192.168.10.48 is down
192.168.10.49 is down
192.168.10.50 is down
192.168.10.51 is down
192.168.10.52 is down
192.168.10.53 is down
192.168.10.54 is down
192.168.10.55 is down
192.168.10.56 is down
192.168.10.57 is down
192.168.10.58 is down
192.168.10.59 is down
192.168.10.60 is down
192.168.10.61 is down
192.168.10.62 is down
192.168.10.63 is down
192.168.10.64 is down
192.168.10.65 is down
192.168.10.66 is down
192.168.10.67 is down
192.168.10.68 is down
192.168.10.69 is down
192.168.10.70 is down
192.168.10.71 is down
192.168.10.72 is down
192.168.10.73 is down
192.168.10.74 is down
192.168.10.75 is down
192.168.10.76 is down
192.168.10.77 is down
192.168.10.78 is down
192.168.10.79 is down
192.168.10.80 is down
192.168.10.81 is down
192.168.10.82 is down
192.168.10.83 is down
192.168.10.84 is down
192.168.10.85 is down
192.168.10.86 is down
192.168.10.87 is down
192.168.10.88 is down
192.168.10.89 is down
192.168.10.90 is down
192.168.10.91 is down
192.168.10.92 is down
192.168.10.93 is down
192.168.10.94 is down
192.168.10.95 is down
192.168.10.96 is down
192.168.10.97 is down
192.168.10.98 is down
192.168.10.99 is down
192.168.10.100 is down
192.168.10.101 is down
192.168.10.102 is down
192.168.10.103 is down
192.168.10.104 is down
192.168.10.105 is down
192.168.10.106 is down
192.168.10.107 is down
192.168.10.108 is down
192.168.10.109 is down
192.168.10.110 is down
192.168.10.111 is down
192.168.10.112 is down
192.168.10.113 is down
192.168.10.114 is down
192.168.10.115 is down
192.168.10.116 is down
192.168.10.117 is down
192.168.10.118 is down
192.168.10.119 is down
192.168.10.120 is down
192.168.10.121 is down
192.168.10.122 is down
192.168.10.123 is down
192.168.10.124 is down
192.168.10.125 is down
192.168.10.126 is down
192.168.10.127 is down
192.168.10.128 is down
192.168.10.129 is down
192.168.10.130 is down
192.168.10.131 is down
192.168.10.132 is down
192.168.10.133 is down
192.168.10.134 is down
192.168.10.135 is down
192.168.10.136 is down
192.168.10.137 is down
192.168.10.138 is down
192.168.10.139 is down
192.168.10.140 is down
192.168.10.141 is down
192.168.10.142 is down
192.168.10.143 is down
192.168.10.144 is down
192.168.10.145 is down
192.168.10.146 is down
192.168.10.147 is down
192.168.10.148 is down
192.168.10.149 is down
192.168.10.150 is down
192.168.10.151 is down
192.168.10.152 is down
192.168.10.153 is down
192.168.10.154 is down
192.168.10.155 is down
192.168.10.156 is down
192.168.10.157 is down
192.168.10.158 is down
192.168.10.159 is down
192.168.10.160 is down
192.168.10.161 is down
192.168.10.162 is down
192.168.10.163 is down
192.168.10.164 is down
192.168.10.165 is down
192.168.10.166 is down
192.168.10.167 is down
192.168.10.168 is down
192.168.10.169 is down
192.168.10.170 is down
192.168.10.171 is down
192.168.10.172 is down
192.168.10.173 is down
192.168.10.174 is down
192.168.10.175 is down
192.168.10.176 is down
192.168.10.177 is down
192.168.10.178 is down
192.168.10.179 is down
192.168.10.180 is down
192.168.10.181 is down
192.168.10.182 is down
192.168.10.183 is down
192.168.10.184 is down
192.168.10.185 is down
192.168.10.186 is down
192.168.10.187 is down
192.168.10.188 is down
192.168.10.189 is down
192.168.10.190 is down
192.168.10.191 is down
192.168.10.192 is down
192.168.10.193 is down
192.168.10.194 is down
192.168.10.195 is down
192.168.10.196 is down
192.168.10.197 is down
192.168.10.198 is down
192.168.10.199 is down
192.168.10.200 is down
192.168.10.201 is down
192.168.10.202 is down
192.168.10.203 is down
192.168.10.204 is down
192.168.10.205 is down
192.168.10.206 is down
192.168.10.207 is down
192.168.10.208 is down
192.168.10.209 is down
192.168.10.210 is down
192.168.10.211 is down
192.168.10.212 is down
192.168.10.213 is down
192.168.10.214 is down
192.168.10.215 is down
192.168.10.216 is down
192.168.10.217 is down
192.168.10.218 is down
192.168.10.219 is down
192.168.10.220 is down
192.168.10.221 is down
192.168.10.222 is down
192.168.10.223 is down
192.168.10.224 is down
192.168.10.225 is down
192.168.10.226 is down
192.168.10.227 is down
192.168.10.228 is down
192.168.10.229 is down
192.168.10.230 is down
192.168.10.231 is down
192.168.10.232 is down
192.168.10.233 is down
192.168.10.234 is down
192.168.10.235 is down
192.168.10.236 is down
192.168.10.237 is down
192.168.10.238 is down
192.168.10.239 is down
192.168.10.240 is down
192.168.10.241 is down
192.168.10.242 is down
192.168.10.243 is down
192.168.10.244 is down
192.168.10.245 is down
192.168.10.246 is down
192.168.10.247 is down
192.168.10.248 is down
192.168.10.249 is down
192.168.10.250 is down
192.168.10.251 is down
192.168.10.252 is down
192.168.10.253 is down
192.168.10.254 is down

[root@localhost /home]# vim demo53.sh
#!/bin/bash
init=123456
for i in {1..3}
do
  read -p "请输入密码:" passwd
  if [ "$passwd" == "$init" ]; then
    echo "密码正确"
  exit
  fi
done
  echo "密码错误"
~ 
[root@localhost /home]# chmod +x demo53.sh
[root@localhost /home]# bash -n demo53.sh
[root@localhost /home]# ./demo53.sh
请输入密码:456789
请输入密码:456221
请输入密码:999754
密码错误
[root@localhost /home]# ./demo53.sh
请输入密码:123456
密码正确

[root@localhost /home]# vim demo54.sh
#!/bin/bash
#set -x
# 创建并初始化文件
touch /opt/name.txt
echo "zhangsan" > /opt/name.txt
echo "lisi" >> /opt/name.txt
echo "wangwu" >> /opt/name.txt
echo "zhaoliu" >> /opt/name.txt
# 初始化计数器
a=0
b=0
c=0
d=0
# 循环10次
for ((i=1; i<=10; i++))
do
  # 生成随机数
  NU=$((RANDOM % 4 + 1))
  # 根据随机数选择名字
  LT=$(sed -n "${NU}p" /opt/name.txt)
 # 根据名字增加相应计数器
  case $LT in
    zhangsan)
      let a++
      ;;
    lisi)
      let b++
      ;;
    wangwu)
      let c++
      ;;
    zhaoliu)
      let d++
      ;;
  esac
  # 输出当前名字
  echo "$LT"
done
# 输出计数结果
echo "zhangsan:$a次,lisi:$b次,wangwu:$c次,zhaoliu:$d次"
~
[root@localhost /home]# chmod +x demo54.sh
[root@localhost /home]# ./demo54.sh
zhaoliu
zhangsan
lisi
wangwu
wangwu
lisi
zhaoliu
zhangsan
zhangsan
zhangsan
zhangsan:4次,lisi:2次,wangwu:2次,zhaoliu:2次
[root@localhost /home]# ./demo54.sh
lisi
wangwu
lisi
zhangsan
wangwu
zhaoliu
zhangsan
wangwu
lisi
wangwu
zhangsan:2次,lisi:3次,wangwu:4次,zhaoliu:1次
[root@localhost /home]# ./demo54.sh
lisi
wangwu
zhaoliu
lisi
lisi
lisi
zhangsan
lisi
zhaoliu
lisi
zhangsan:1次,lisi:6次,wangwu:1次,zhaoliu:2次
[root@localhost /home]# ./demo54.sh
wangwu
lisi
zhangsan
wangwu
lisi
lisi
zhangsan
wangwu
wangwu
wangwu
zhangsan:2次,lisi:3次,wangwu:5次,zhaoliu:0次

 2.while循环语句

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

while循环一般用于有条件判断的循环,若判断条件为真,则进入循环,当条件为假就跳出循环

格式

while条件测试操作
do

命令序列
done

[root@localhost /home]# vim demo55.sh
#!/bin/bash
i=1
while [ $i -le 5 ]
do
  echo $i
  let i++
done
  echo "最后的值为:$i"
~  
[root@localhost /home]# chmod +x demo55.sh
[root@localhost /home]# ./demo55.sh
1
2
3
4
5
最后的值为:6

[root@localhost /home]# vim demo56.sh
#!/bin/bash
i=1
while [ $i -le 100 ]
do
if [[ $i%3 -ne 0 ]]; then
  echo "$i"
fi
  let i++
done
~     
[root@localhost /home]# chmod +x demo56.sh
[root@localhost /home]# ./demo56.sh
1
2
4
5
7
8
10
11
13
14
16
17
19
20
22
23
25
26
28
29
31
32
34
35
37
38
40
41
43
44
46
47
49
50
52
53
55
56
58
59
61
62
64
65
67
68
70
71
73
74
76
77
79
80
82
83
85
86
88
89
91
92
94
95
97
98
100

[root@localhost /home]# vim demo57.sh
#!/bin/bash
i=1
sum=0
while [ $i -le 100 ]
do
  let sum=$i+$sum
  ((i++))
done
echo $sum
~  
[root@localhost /home]# chmod +x demo57.sh
[root@localhost /home]# ./demo57.sh
5050

[root@localhost /home]# vim demo58.sh
#!/bin/bash
while ps aux|grep httpd|grep -v grep &> /dev/null
do
  echo "httpd 正在运行中"
  sleep 2
done
  echo "httpd 不在运行"
~ 
[root@localhost /home]# chmod +x demo58.sh
[root@localhost /home]# ./demo58.sh
http 不在运行
[root@localhost /home]# systemctl start httpd
[root@localhost /home]# ./demo58.sh
httpd 正在运行中
httpd 正在运行中
httpd 正在运行中
^C

[root@localhost /home]# vim demo59.sh
#!/bin/bash
num=10
while true
do
read -p "请输入数字:" shu
  if [ $shu -eq $num ]; then
    echo "猜对了"
    break
  elif [ $shu -gt $num ]; then
    echo "猜大了"
  elif [ $shu -lt $num ]; then
    echo "猜小了"
  fi
done
~   
[root@localhost /home]# chmod +x demo59.sh
[root@localhost /home]# ./demo59.sh
请输入数字:100
猜大了
请输入数字:9       
猜小了
请输入数字:10
猜对了

[root@localhost /home]# vim demo60.sh
#!/bin/bash
USER="fxfxfx"
i=1
while [ $i -le 20 ]
do
  # 添加用户
  useradd ${USER}${i}

  # 为新用户设置密码
  echo "123456" | passwd --stdin ${USER}${i} &> /dev/null

  # 递增计数器
  ((i++))
done
~  
[root@localhost /home]# chmod +x demo60.sh
[root@localhost /home]# ./demo60.sh
[root@localhost /home]# tail -20 /etc/passwd
fxfxfx1:x:10146:10146::/home/fxfxfx1:/bin/bash
fxfxfx2:x:10147:10147::/home/fxfxfx2:/bin/bash
fxfxfx3:x:10148:10148::/home/fxfxfx3:/bin/bash
fxfxfx4:x:10149:10149::/home/fxfxfx4:/bin/bash
fxfxfx5:x:10150:10150::/home/fxfxfx5:/bin/bash
fxfxfx6:x:10151:10151::/home/fxfxfx6:/bin/bash
fxfxfx7:x:10152:10152::/home/fxfxfx7:/bin/bash
fxfxfx8:x:10153:10153::/home/fxfxfx8:/bin/bash
fxfxfx9:x:10154:10154::/home/fxfxfx9:/bin/bash
fxfxfx10:x:10155:10155::/home/fxfxfx10:/bin/bash
fxfxfx11:x:10156:10156::/home/fxfxfx11:/bin/bash
fxfxfx12:x:10157:10157::/home/fxfxfx12:/bin/bash
fxfxfx13:x:10158:10158::/home/fxfxfx13:/bin/bash
fxfxfx14:x:10159:10159::/home/fxfxfx14:/bin/bash
fxfxfx15:x:10160:10160::/home/fxfxfx15:/bin/bash
fxfxfx16:x:10161:10161::/home/fxfxfx16:/bin/bash
fxfxfx17:x:10162:10162::/home/fxfxfx17:/bin/bash
fxfxfx18:x:10163:10163::/home/fxfxfx18:/bin/bash
fxfxfx19:x:10164:10164::/home/fxfxfx19:/bin/bash
fxfxfx20:x:10165:10165::/home/fxfxfx20:/bin/bash

[root@localhost /home]# vim demo61.sh
#!/bin/bash
PRICE=$(( RANDOM % 1000 ))
a=0
echo "商品实际价格范围是0~999,猜一猜是多少?"
while true
do
read -p "请输入猜测的价格数目:" n
((a++))
if [ $n -eq $PRICE ]; then
  echo "答对了,实际价格是$PRICE"
  echo "总共猜测了$a次"
  exit 0
elif [ $n -gt $PRICE ]; then
  echo "价格猜高了"
else
  echo "价格猜低了"
fi
done
~ 
[root@localhost /home]# chmod +x demo61.sh
[root@localhost /home]# ./demo61.sh
商品实际价格范围是0~999,猜一猜是多少?
请输入猜测的价格数目:99999999
价格猜高了
请输入猜测的价格数目:800    
价格猜低了
请输入猜测的价格数目:900
价格猜高了
请输入猜测的价格数目:890
价格猜高了
请输入猜测的价格数目:880
价格猜高了
请输入猜测的价格数目:870
价格猜高了
请输入猜测的价格数目:860
价格猜高了
请输入猜测的价格数目:850
价格猜高了
请输入猜测的价格数目:842
价格猜高了
请输入猜测的价格数目:830
价格猜高了
请输入猜测的价格数目:820
价格猜高了
请输入猜测的价格数目:810
答对了,实际价格是810
总共猜测了12次

[root@localhost /home]# vim demo62.sh
#!/bin/bash
sorce=$[ $RANDOM % 1000 ]
a=1
num=0
while [ $a -lt 2 ]
do
read -p "请输入你猜测的价格(0~999之间):" price
if [ $price -eq $sorce ]; then
  echo "猜测对了"
let num++
let a++
elif [ $price -gt $sorce ]; then
  echo "价格猜测高了"
elif [$sprice -lt $sorce ]; then
  echo "价格猜测低了"
let num++
fi
done
  echo "共猜测$num次" 
~
[root@localhost /home]# chmod +x demo62.sh
[root@localhost /home]# ./demo62.sh
商品实际价格范围是0~999,猜一猜是多少?
请输入猜测的价格数目:900
价格猜高了
请输入猜测的价格数目:450
价格猜低了
请输入猜测的价格数目:750
价格猜高了
请输入猜测的价格数目:600
价格猜低了
请输入猜测的价格数目:680
价格猜高了
请输入猜测的价格数目:670   
价格猜高了
请输入猜测的价格数目:666 
价格猜高了
请输入猜测的价格数目:620
价格猜低了
请输入猜测的价格数目:635
价格猜高了
请输入猜测的价格数目:624
价格猜低了
请输入猜测的价格数目:628
价格猜低了
请输入猜测的价格数目:629   
价格猜低了
请输入猜测的价格数目:632
价格猜低了
请输入猜测的价格数目:639
价格猜高了
请输入猜测的价格数目:637
价格猜高了
请输入猜测的价格数目:634
价格猜高了
请输入猜测的价格数目:633
答对了,实际价格是633
总共猜测了17次

sorce=$(( RANDOM % 1000 ))
a=0
num=0

while [ $a -lt 1 ] && [ $num -lt 5 ]
do
  read -p "请输入你猜测的价格(0~999之间):" price
  let num++
  if [ $price -eq $sorce ]; then
    echo "猜测对了"
    let a=1
  elif [ $price -gt $sorce ]; then
    echo "价格猜测高了"
  elif [ $price -lt $sorce ]; then
    echo "价格猜测低了"
  fi
done

if [ $a -eq 1 ]; then
  echo "你猜对了,共猜测了$num次"
else
  echo "很遗憾,你已经猜测了5次。正确的价格是 $sorce。"
fi
[root@localhost /home]# C demo63.sh 
[root@localhost /home]# ./demo63.sh
请输入你猜测的价格(0~999之间):500
价格猜测高了
请输入你猜测的价格(0~999之间):320
价格猜测高了
请输入你猜测的价格(0~999之间):280
价格猜测高了
请输入你猜测的价格(0~999之间):150
价格猜测低了
请输入你猜测的价格(0~999之间):270
价格猜测高了
很遗憾,你已经猜测了5次。正确的价格是 263。

[root@localhost /home]# vim demo65.sh
#!/bin/bash
# 定义网卡流量单位
DW=kb/s
while :
do
  # 定义某一时间点的提取网卡流量数值
  OLD_IN=$(cat /proc/net/dev | awk '$1 ~ /ens33/ {print $2}')
  OLD_OUT=$(cat /proc/net/dev | awk '$1 ~ /ens33/ {print $10}')
  sleep 5
  # 定义下个时间点的提取网卡流量值
  NEW_IN=$(cat /proc/net/dev | awk '$1 ~ /ens33/ {print $2}')
  NEW_OUT=$(cat /proc/net/dev | awk '$1 ~ /ens33/ {print $10}')
  # 进行流量计算,默认是bytes,转换成kb/s
  IN=$(echo "($NEW_IN - $OLD_IN) / 1024 / 5" | bc)
  OUT=$(echo "($NEW_OUT - $OLD_OUT) / 1024 / 5" | bc)
  # 打印对应的值
  echo -e "接收数据:${IN}${DW}\t发送数据:${OUT}${DW}"
done
~         
[root@localhost /home]# chmod +x demo65.sh
[root@localhost /home]# ./demo65.sh
接收数据:0kb/s	发送数据:0kb/s
接收数据:0kb/s	发送数据:0kb/s
接收数据:0kb/s	发送数据:0kb/s
接收数据:0kb/s	发送数据:0kb/s
接收数据:0kb/s	发送数据:0kb/s
接收数据:0kb/s	发送数据:0kb/s
接收数据:0kb/s	发送数据:0kb/s
接收数据:0kb/s	发送数据:0kb/s
接收数据:0kb/s	发送数据:0kb/s
接收数据:1kb/s	发送数据:0kb/s
接收数据:0kb/s	发送数据:0kb/s
接收数据:30kb/s	发送数据:2kb/s
接收数据:33kb/s	发送数据:6kb/s
接收数据:18kb/s	发送数据:7kb/s
接收数据:73kb/s	发送数据:8kb/s
接收数据:95kb/s	发送数据:11kb/s
接收数据:42kb/s	发送数据:5kb/s

[root@localhost /home]# vim demo66.sh
#!/bin/bash
i=1
sum=0

while [ $i -le 5 ]
do
  echo "进入第$i商店"
  read -p "是否进入看看(yes/no): " doing

  while [ "$doing" = "yes" ]
  do
    echo "1: 衣服 ¥300"
    echo "2: 鞋子 ¥200"
    echo "3: 手套 ¥50"
    echo "4: 袜子 ¥150"
    read -p "请输入需要购买的商品序号: " num

    case $num in
      1)
        echo "衣服购买成功"
        sum=$((sum + 300))
        ;;
      2)
        echo "鞋子购买成功"
        sum=$((sum + 200))
        ;;
      3)
        echo "手套购买成功"
        sum=$((sum + 50))
        ;;
      4)
        echo "袜子购买成功"
        sum=$((sum + 150))
        ;;
      *)
        echo "无效的商品序号"
        ;;
    esac

    read -p "是否继续进行购买(yes/no): " doing
  done

  let i++
  if [ "$doing" = "no" ]; then
    continue
  fi
done

echo "购物总价: ¥$sum"
~
[root@localhost /home]# chmod +x demo66.sh
[root@localhost /home]# ./demo66.sh
进入第1商店
是否进入看看(yes/no): no
进入第2商店
是否进入看看(yes/no): yes
1: 衣服 ¥300
2: 鞋子 ¥200
3: 手套 ¥50
4: 袜子 ¥150
请输入需要购买的商品序号: 4
袜子购买成功
是否继续进行购买(yes/no): no
进入第3商店
是否进入看看(yes/no): yes
1: 衣服 ¥300
2: 鞋子 ¥200
3: 手套 ¥50
4: 袜子 ¥150
请输入需要购买的商品序号: 1
衣服购买成功
是否继续进行购买(yes/no): no
进入第4商店
是否进入看看(yes/no): yes
1: 衣服 ¥300
2: 鞋子 ¥200
3: 手套 ¥50
4: 袜子 ¥150
请输入需要购买的商品序号: 3
手套购买成功
是否继续进行购买(yes/no): no
进入第5商店
是否进入看看(yes/no): no
购物总价: ¥500

3.untli循环语句

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

格式

[root@localhost /home]# vim demo67.sh

#!/bin/bash
i=0
s=0
until [ $i -eq 21 ]
do
        let s+=i  #s+=i和s=s+i,使用附加值
        let i++
done
echo $s
~
[root@localhost /home]# chmod +x demo67.sh
[root@localhost /home]# ./demo67.sh
210

[root@localhost /home]# vim demo68.sh
#!/bin/bash
username=$1
message=${*:2}

# 判断信息格式
if [ $# -lt 1 ]; then
  echo "Usage: `basename $0` <username> [<message>]"
  exit 1
fi

# 判断用户是否存在
if grep "^$username:" /etc/passwd > /dev/null; then
  :
else
  echo "用户不存在"
  exit 1
fi

# 用户是否在线,如果不在线每5秒检查一次
until who | grep "$username" > /dev/null
do
  echo "用户不在线"
  sleep 5
done

# 发送信息给用户
echo "$message" | write $username
~
[root@localhost /home]# chmod +x demo68.sh
[root@localhost /home]# ./demo68.sh
Usage: demo68.sh <username> [<message>]
[root@localhost /home]# ./demo68.sh zhangsan
用户不在线
用户不在线
用户不在线
^C

2.循环控制语句

for循环一般会搭配条件判断语句和流程控制语句一起执行,那么就会出现需要跳过循环和中止循环的情况,控制循环的命令有3个

  • continue
  • break
  • exit

1 . continue

继续,但不会执行循环体内下面的代码了,开始重新开始下一次循环

[root@localhost /home]# vim demo69.sh
#!/bin/bash
for ((i=1;i<=5;i++))
do
  if [ $i -eq 3 ]; then
  continue
  else
  echo $i
  fi
done
~ 
[root@localhost /home]# chmod +x demo69.sh
[root@localhost /home]# ./demo69.sh
1
2
4
5

2 . break

打断,马上停止本次循环,执行循环体外的代码

[root@localhost /home]# vim demo70.sh
#!/bin/bash
for ((i=1;i<=10;i++))
do
  if [ $i -eq 8 ]; then
  break
  else
  echo $i
  fi
done
~ 
[root@localhost /home]# bash -n demo70.sh
[root@localhost /home]# ./demo70.sh
-bash: ./demo70.sh: 权限不够
[root@localhost /home]# chmod +x demo70.sh
[root@localhost /home]# ./demo70.sh
1
2
3
4
5
6
7

3 . exit

[root@localhost /home]# vim demo71.sh
#!/bin/bash
for i in {1..5}
do
  if [ $i -eq 3 ]; then
    exit 100
  else
    echo $i
  fi
done
echo hi
~ 
[root@localhost /home]# chmod +x demo71.sh
[root@localhost /home]# ./demo71.sh
1
2

二,shell函数

Shell 函数是指在Unix或Linux系统的shell中定义的函数。Shell是一种命令行解释器,常见的有Bash、Zsh、Sh等。通过定义Shell函数,可以将常用的一组命令封装在一起,便于重复使用,从而提高效率和代码的可读性。

1. 函数定义

格式

function function_name {
    # 函数体
}

function_name() {
    # 函数体
}

函数定义完之后并不会自动执行,需要调用才行,好处在于可以写一段功能代码作为函数,有需要就直接调用

定义,写函数最终目是为了调用,为了实现某个功能块

2.函数返回退出

2.1使用 return 结束函数

return 主要用于函数内部,返回到函数调用处,并可以返回一个状态码(0-255)

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

1.函数一结束就取返回值:因为$?变量只返回执行的最后一条命令的退出状态码,所以需要在函数执行结束后立即获取返回值。

2.退出状态码范围:退出状态码必须在0到255之间,超出此范围的值将取余256。

my_function() {
    return 444
}

my_function
echo $?

函数my_function返回值444。但是,因为返回值必须在0到255之间,值444将被取余256

444 % 256 = 188

因此,echo $?输出188

#!/bin/bash

# 定义函数 test1
function test1 {
    read -p "请输入一个数字: " num
    if [ $num -lt 0 ]; then
        echo "数字不能是负数"
        return 1
    fi
    return $((num * 2))
}

# 调用函数 test1
test1

# 获取并打印函数 test1 的返回值
result1=$?
echo "test1 函数返回的值: $result1"

if [ $result1 -eq 1 ]; then
    echo "错误:输入了负数"
else
    echo "test1 函数返回的值: $result1"
fi

2.1使用 exit 结束脚本

exit 用于终止整个脚本,并返回一个状态码。

#!/bin/bash

# 定义函数 test2
function test2 {
    read -p "请输入值2: " NUM
    if [ $NUM -lt 0 ]; then
        echo "数字不能是负数"
        exit 1
    fi
    echo $((NUM * 2))
}

# 调用函数 test2 并捕获其输出
res=$(test2)
exit_status=$?

# 检查 exit 状态码
if [ $exit_status -eq 1 ]; then
    echo "错误:输入了负数"
    exit 1
fi

echo "test2 函数返回的值: $res"

# 进一步处理 test2 的返回值
final_result=$((res * 2))
echo "最终的结果是: $final_result"

3.函数的调用

3.1函数调用注意事项

  • 函数名必须唯一,避免重名。
  • 函数在被调用之前必须已经定义好。
  • 函数可以在脚本的任何位置定义,只要在调用之前定义即可。
  • 在嵌套调用中,使用反撇号(`)或 $(...) 来调用函数并获取其结果。
a.函数名必须唯一

函数名在同一个脚本中必须唯一。如果重新定义一个已经存在的函数名,新的定义会覆盖旧的定义。

#!/bin/bash

f1 (){
    echo hello
}

f1 (){
    echo world
}

f1  # 输出: world

在这个例子中,第二个 f1 函数覆盖了第一个 f1 函数,所以最后调用 f1 输出的是 world

b.调用函数之前必须先定义

在调用函数之前,函数必须已经定义好。如果在调用一个函数时,另一个被调用的函数还没有定义,就会出现错误。

错误示例
#!/bin/bash

f1 (){
    echo hello
}

f3 (){
    echo "$(f1) $(f2)"
}

f2 (){
    echo world
}

f3  # 运行时会报错: f2: 未找到命令

在这个例子中,f3 调用了 f2,但是 f2 的定义在 f3 之后,所以运行时会报错。

正确示例
#!/bin/bash

f1 (){
    echo hello
}

f2 (){
    echo world
}

f3 (){
    echo "$(f1) $(f2)"
}

f3  # 输出: hello world

在这个正确的示例中,所有函数在被调用之前都已经定义好,所以脚本可以正常运行。

c.函数定义的位置

函数不一定要在脚本的开头定义,只要在调用之前定义即可。

#!/bin/bash

f3 (){
    echo "$(f1) $(f2)"
}

f1 (){
    echo hello
}

f2 (){
    echo world
}

f3  # 输出: hello world

在这个例子中,虽然函数定义的位置不同,但只要在调用之前定义,脚本都可以正常运行。

d.嵌套调用时的注意事项

在嵌套调用中,如果直接写函数名,会打印函数名本身,而不是函数的输出。使用反撇号(`)或 $(...) 可以调用函数并获得其结果。

#!/bin/bash

f1 (){
    echo hello
}

f2 (){
    echo world
}

f3 (){
    echo "`f1` `f2`"  # 使用反撇号调用函数
}

f3  # 输出: hello world

或使用 $(...)

#!/bin/bash

f1 (){
    echo hello
}

f2 (){
    echo world
}

f3 (){
    echo "$(f1) $(f2)"  # 使用 $(...) 调用函数
}

f3  # 输出: hello world

4.函数传递参数

[root@localhost /home]# vim demo73.sh
#!/bin/bash
sum(){
read -p "请输入第一个数" NU1
read -p "请输入第二个数" NU2
echo "输入的数字分别为$NU1和$NU2"
SUM=$(($NU1+$NU2))
echo "两个数的和为:$SUM"
}
sum
~     
[root@localhost /home]# chmod +x demo73.sh
[root@localhost /home]# ./demo73.sh
请输入第一个数10
请输入第二个数30
输入的数字分别为10和30
两个数的和为:40

5.函数的作用范围

在 Shell 脚本中,函数的执行在当前的 Shell 环境中进行,不会开启新的子 Shell。因此,除特别指定,函数内定义的变量在整个脚本中都是全局有效的。这意味着,函数内的变量可以在函数外部访问和修改。

编写脚本时,有时需要将变量的值限定在函数内部,可以通过内置命令local来实现。函数内部变量的作用,可以避免函数内外同时出现同名变量对脚本结果的影响。

[root@localhost /home]# vim demo74.sh
#!/bin/bash
myii(){
local i
i=8     #内部变量
echo $i
}
i=9     #全局变量
myii
echo $i
~   
[root@localhost /home]# chmod +x demo74.sh
[root@localhost /home]# ./demo74.sh
8
9

函数内部使用了local命令设置变量i,其作用是将变量i限定在函数内部。myii 函数外部同样定义了变量i,内部变量i和全局变量i互不影响。

6.函数的参数

6.1 函数参数

在 Bash 中,函数是一段可以重复调用的代码。你可以传递参数给函数,这些参数在函数内部使用位置变量 $1, $2 等来访问。

#!/bin/bash
add (){
    let sum=$1+$2   # 计算两个参数的和,是函数的位置变量,要写在调用函数的后面,如调用脚本时使用则不能调用

    echo $sum       # 输出结果
}
add 4 5        # 调用函数 add,传递两个参数 4 和 5    

在这个例子中,add 函数接收两个参数,计算它们的和并输出结果。函数内的 $1$2 是函数的局部变量,代表传递给函数的第一个和第二个参数。

6.2 脚本参数

Bash 脚本也可以接收参数,这些参数在脚本中同样用 $1, $2 等位置变量表示。当你运行脚本时,可以通过命令行传递参数,脚本会自动获取这些参数并进行处理。

#!/bin/bash
add (){
    let sum=$1+$2   # 计算两个参数的和
    echo $sum       # 输出结果
}

add $1 $2           # 调用函数,使用脚本的第一个和第二个位置参数  调用了脚本的参数,把脚本的位置变量传递给函数进行计算

7.函数的递归

列出目录内文件列表,目录用蓝色表示,文件显示层级关系

[root@localhost /home]# vim demo79.sh
#!/bin/bash
list(){
for i in $1/*
do
  if [ -d $i ];then
    echo -e "\e[34m$i\e[0m"
    list $i"$2"
  else
    echo "$2$i"
  fi
done
}
list $1 $2
~ 
[root@localhost /home]# chmod +x demo79.sh 
[root@localhost /home]# ./demo79.sh /opt
/opt/001.txt
/opt/002.txt
/opt/003.txt
/opt/011.txt
/opt/022.txt
/opt/033.txt
/opt/100
/opt/100/111.txt
/opt/100/1.txt
/opt/10000
/opt/10000/102.txt
/opt/111
/opt/111/a1
/opt/111/a1/a2
/opt/111/a1/a2/a12.txt
/opt/200
/opt/200/222.txt
/opt/200/2.txt
/opt/222
/opt/222/b1
/opt/222/b1/b2
/opt/222/b1/b2/b12.txt
/opt/300
/opt/300/333.txt
/opt/300/3.txt
/opt/333
/opt/333/c1
/opt/333/c1/c2
/opt/333/c1/c2/c12.txt
/opt/44
/opt/a10000
/opt/a10000/ztw1.txt
/opt/f22
/opt/f33
/opt/f44
/opt/name.txt
/opt/passwd
/opt/rh
/opt/rh/1001

8.计算阶乘

[root@localhost /home]# vim demo80.sh
#!/bin/bash

# 定义计算阶乘的函数
fa(){
if [ $1 -eq 1 ]; then
    echo 1
  else
    local pp=$(( $1 - 1 ))
    local res=$(fa $pp)
    echo $(( $1 * $res ))
  fi
}

# 提示用户输入一个数字
read -p "请输入:" num

# 调用函数并捕获结果
res=$(fa $num)

# 输出结果
echo $res
~  
[root@localhost /home]# chmod +x demo80.sh
[root@localhost /home]# ./demo80.sh
请输入:5  
120
[root@localhost /home]# ./demo80.sh
请输入:6
720

5

fa 5 $1=5 tp=4 res=fa 4 echo 5 * fa 4 5*4*3*2*1

fa 4 $1=4 tp=3 res=fa 3 echo 4 * fa 3 4*3*2*1

fa 3 $1=3 tp=2 res=fa 2 echo 3 * fa 2 3*2*1

fa 2 $1=2 tp=1 res=fa 1 echo 2 * fa 1 2*1

fa 1 $1=1 echo 1

6

同上

三,Shell数组

数组是存放相同类型数据的集合,在内存中开辟了连续的空间,通常配合循环使用

1.根据用途分类

  • 普通数组:用于存储一般数据。不需要声明直接定义,下标索引只能是整数
  • 关联数组:使用键值对存储数据(类似于字典)。需要用declare -A声明否则系统不识别,索引可以是字符串

2.数组的定义

80 90 60 20 70 50 30 40 10

0 1 2 3 4 5 6 7 8

2.1直接初始化数组

这种方法通过将要加入数组的元素用小括号括起来,中间用空格分开。

#!/bin/bash

# 直接初始化数组
num=(11 22 33 44)

# 打印数组的所有元素
echo "数组的所有元素: ${num[@]}"

# 打印数组的长度
echo "数组的长度: ${#num[@]}"

2.2指定索引初始化数组

这种方法通过精确地给每一个下标索引定义一个值加入数组,索引数字可以不连续。

#!/bin/bash

# 指定索引初始化数组
num=([0]=55 [1]=66 [2]=77 [4]=88)

# 打印数组的所有元素
echo "数组的所有元素: ${num[@]}"

# 打印数组的长度
echo "数组的长度: ${#num[@]}"

# 打印数组的索引
echo "数组的索引: ${!num[@]}"

2.3先赋值给变量,然后引用变量初始化数组

这种方法通过先把要加入数组的元素全部赋值给一个变量,然后引用这个变量加入到数组。

#!/bin/bash

# 先赋值给变量
list="11 12 13 14"

# 引用变量初始化数组
num=($list)

# 打印数组的所有元素
echo "数组的所有元素: ${num[@]}"

# 打印数组的长度
echo "数组的长度: ${#num[@]}"

2.4根据下标定义数组

这种方法通过根据下标逐个定义数组元素。

#!/bin/bash

# 根据下标定义数组
num[0]="11"
num[1]="22"
num[2]="33"
num[3]="44"

# 打印数组的所有元素
echo "数组的所有元素: ${num[@]}"

# 打印数组的长度
echo "数组的长度: ${#num[@]}"

3.冒泡排序

冒泡排序(Bubble Sort)是一种简单且经典的排序算法。通过多次遍历要排序的列表,比较相邻元素并交换它们的位置,从而使数据按照指定的顺序排列。尽管冒泡排序并不是最有效的排序算法,但它的简单性使其成为学习排序算法的入门选择。

3.1冒泡排序是什么

冒泡排序通过重复地遍历列表,比较相邻的元素并根据大小关系交换它们的位置。每一轮遍历都会将一个最大或最小的元素“冒泡”到列表的一端。因此,经过 n-1 轮遍历后,整个列表就变得有序了。

3.2冒泡排序的步骤

  1. 从列表的第一个元素开始,比较每对相邻的元素。
  2. 如果前一个元素比后一个元素大,则交换它们的位置。
  3. 重复上述步骤,直到遍历完整个列表。
  4. 对列表进行多次遍历,直到没有需要交换的元素为止


#!/bin/bash

# 定义一个冒泡排序函数
bubble_sort() {
    local array=("$@")
    local n=${#array[@]}
    local temp

    for ((i = 0; i < n; i++)); do
        echo "第 $((i+1)) 轮排序开始:"
        for ((j = 0; j < n-i-1; j++)); do
            if (( array[j] > array[j+1] )); then
                # 交换 array[j] 和 array[j+1]
                temp=${array[j]}
                array[j]=${array[j+1]}
                array[j+1]=$temp
                # 打印当前步骤的数组状态
                echo "  交换 ${array[j+1]} 和 ${array[j]}: ${array[@]}"
            fi
        done
        # 打印每轮结束后的数组状态
        echo "第 $((i+1)) 轮排序结果: ${array[@]}"
    done
    echo "最终排序结果: ${array[@]}"
}

# 示例数组
num=(64 34 25 12 22 11 90)

# 打印排序前的数组
echo "排序前的数组: ${num[@]}"

# 调用冒泡排序函数并存储排序后的数组
bubble_sort "${num[@]}"

运行脚本

将上述代码保存到一个文件(例如 bubble_sort.sh),然后在终端运行该脚本:

bash bubble_sort.sh

输出结果示例

运行脚本后,你将看到类似以下的输出,每一步交换和每轮排序后的数组状态都会被打印出来:

排序前的数组: 64 34 25 12 22 11 90
第 1 轮排序开始:
  交换 64 和 34: 34 64 25 12 22 11 90
  交换 64 和 25: 34 25 64 12 22 11 90
  交换 64 和 12: 34 25 12 64 22 11 90
  交换 64 和 22: 34 25 12 22 64 11 90
  交换 64 和 11: 34 25 12 22 11 64 90
第 1 轮排序结果: 34 25 12 22 11 64 90
第 2 轮排序开始:
  交换 34 和 25: 25 34 12 22 11 64 90
  交换 34 和 12: 25 12 34 22 11 64 90
  交换 34 和 22: 25 12 22 34 11 64 90
  交换 34 和 11: 25 12 22 11 34 64 90
第 2 轮排序结果: 25 12 22 11 34 64 90
第 3 轮排序开始:
  交换 25 和 12: 12 25 22 11 34 64 90
  交换 25 和 22: 12 22 25 11 34 64 90
  交换 25 和 11: 12 22 11 25 34 64 90
第 3 轮排序结果: 12 22 11 25 34 64 90
第 4 轮排序开始:
  交换 22 和 11: 12 11 22 25 34 64 90
第 4 轮排序结果: 12 11 22 25 34 64 90
第 5 轮排序开始:
  交换 12 和 11: 11 12 22 25 34 64 90
第 5 轮排序结果: 11 12 22 25 34 64 90
第 6 轮排序开始:
第 6 轮排序结果: 11 12 22 25 34 64 90
第 7 轮排序开始:
第 7 轮排序结果: 11 12 22 25 34 64 90
最终排序结果: 11 12 22 25 34 64 90

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值